# PHP

## Supported versions <a href="#supported-versions" id="supported-versions"></a>

The level of support for a language is defined as follows:

* Fully supported: Analysis will complete. All the language features are understood and examined.
* Supported: Most language features are understood and examined but the version includes unsupported features. Analysis might break or provide incomplete results.

PHP versions 5.0 to 8.4 are fully supported.

## Supported frameworks and tools <a href="#supported-frameworks-and-tools" id="supported-frameworks-and-tools"></a>

Laravel, Symfony, WordPress, Laminas, and Zend.

## Language-specific properties <a href="#language-specific-properties" id="language-specific-properties"></a>

Discover and update the PHP-specific [analysis-parameters](https://docs.sonarsource.com/sonarqube-server/analyzing-source-code/analysis-parameters "mention") by going to **Administration** > **Configuration** > **General Settings** > **Languages** > **PHP**

## Turning issues off <a href="#turning-issues-off" id="turning-issues-off"></a>

The best way to deactivate an individual issue you don’t intend to fix is to mark it as accepted or false positive through the Sonar UI.

If you need to deactivate a rule (or all rules) for an entire file, then issue exclusions are the way to go. But if you only want to deactivate a rule across a subset of a file - all the lines of a method or a class - you can use a PHPDoc comment `/* @SuppressWarnings("php:S2077") */` or an attribute `#[SuppressWarnings("php:S2077")]`.

## Analyze php.ini Files <a href="#analyze-files" id="analyze-files"></a>

The PHP analyzer can analyze `php.ini` files with some specific rules (if these rules are activated in your quality profile). `php.ini` files must be part of the project you are analyzing, meaning the `php.ini` files have to be inside the directories listed in `sonar.sources`. Rules targeting `php.ini` files can be quickly identified through the *php-ini* tag set on them.

## Custom Rules <a href="#custom-rules" id="custom-rules"></a>

### Overview <a href="#overview" id="overview"></a>

The PHP analyzer parses the source code, creates an Abstract Syntax Tree (AST), and then walks through the entire tree. A coding rule is a visitor that is able to visit nodes from this AST.

As soon as the coding rule visits a node, it can navigate its children and log issues if necessary.

### Example plugin <a href="#example-plugin" id="example-plugin"></a>

To get started a sample plugin can be found here: [php-custom-rules-plugin](https://github.com/SonarSource/sonar-php/tree/master/php-custom-rules-plugin).

### Writing a plugin <a href="#writing-a-plugin" id="writing-a-plugin"></a>

Custom rules for PHP can be added by writing a SonarQube Server plugin and using PHP analyzer APIs. Here are the steps to follow:

**Create a SonarQube Server plugin**

* create a standard SonarQube Server plugin project
* attach this plugin to the SonarQube PHP analyzer through the `pom.xml` (Gradle Kotlin: `build.gradle.kts` )
* implement the following extension points:
  * [Plugin](https://javadocs.sonarsource.org/latest/org/sonar/api/Plugin.html)
  * [RulesDefinition](https://javadocs.sonarsource.org/latest/org/sonar/api/server/rule/RulesDefinition.html) and [PHPCustomRuleRepository](https://github.com/SonarSource/sonar-php/blob/master/php-frontend/src/main/java/org/sonar/plugins/php/api/visitors/PHPCustomRuleRepository.java), which can be implemented by a single class, to declare your custom rules
* declare the RulesDefinition as an extension in the Plugin extension point.

**Implement a rule**

* create a class that will hold the implementation of the rule, it should:
  * extend `PHPVisitorCheck` or `PHPSubscriptionCheck`
  * define the rule name, key, tags, etc. with Java annotations.
* declare this class in the `RulesDefinition`.

**Implementation details**

**Using** **`PHPVisitorCheck`**

To explore a part of the AST, override a method from the PHPVisitorCheck. For example, if you want to explore "if statement" nodes, override [PHPVisitorCheck#visitIfStatement](https://github.com/SonarSource/sonar-php/blob/master/php-frontend/src/main/java/org/sonar/plugins/php/api/visitors/PHPVisitorCheck.java#L265) method that will be called each time an [ifStatementTree](https://github.com/SonarSource/sonar-php/blob/master/php-frontend/src/main/java/org/sonar/plugins/php/api/tree/statement/IfStatementTree.java) node is encountered in the AST.

When overriding a visit method, you must call the super method in order to allow the visitor to visit the children of the node.

**Using** **`PHPSubscriptionCheck`**

To explore a part of the AST, override [`PHPSubscriptionCheck#nodesToVisit`](https://github.com/SonarSource/sonar-php/blob/master/php-frontend/src/main/java/org/sonar/plugins/php/api/visitors/PHPSubscriptionCheck.java#L33) by returning the list of the [`Tree#Kind`](https://github.com/SonarSource/sonar-php/blob/master/php-frontend/src/main/java/org/sonar/plugins/php/api/tree/Tree.java#L124) of node you want to visit. For example, if you want to explore "if statement" nodes the method will return a list containing the element [`Tree#Kind#IF_STATEMENT`](https://github.com/SonarSource/sonar-php/blob/master/php-frontend/src/main/java/org/sonar/plugins/php/api/tree/Tree.java#L761).

**Create Issues**

From the check, the issue can be created by calling [`CheckContext#newIssue`](https://github.com/SonarSource/sonar-php/blob/master/php-frontend/src/main/java/org/sonar/plugins/php/api/visitors/CheckContext.java#L90) method.

**Testing Checks**

To test custom checks you can use the method [`PHPCheckVerifier#verify`](https://github.com/SonarSource/sonar-php/blob/master/php-frontend/src/main/java/org/sonar/plugins/php/api/tests/PHPCheckVerifier.java#L55). You should end each line with an issue with a comment in the following form:

```css-79elbk
// Noncompliant {{Message}}
```

Comment syntax is described [here](https://github.com/SonarSource/sonar-analyzer-commons/blob/master/test-commons/README.md).

### Configuring plugins for analyzer loading optimization <a href="#configuring-plugins-for-analyzer-loading-optimization" id="configuring-plugins-for-analyzer-loading-optimization"></a>

By default, the loading of analyzers is optimized (see [Improving performance](https://app.gitbook.com/s/iJj3TXBdWssTGGg8qK5I/server-upgrade-and-maintenance/maintenance/improving-performance "mention")), SonarQube Server will only download analyzers and third-party plugins for the detected languages before running an analysis.

When creating custom plugins, to prevent errors when projects are analyzed, "you must use the `requiredForLanguages` property in your plugin’s `pom.xml` file (Gradle: `Plugin-RequiredForLanguages` in the MANIFEST directly) to specify the languages your plugin supports. Without this property, your plugin will be executed unconditionally during analysis, even when its language-specific dependencies are unavailable. See [plugin-basics](https://docs.sonarsource.com/sonarqube-server/extension-guide/developing-a-plugin/plugin-basics "mention") for details on this behavior and the `requiredForLanguages` property.

{% tabs %}
{% tab title="MAVEN" %}
Using the `sonar-packaging-maven-plugin` configuration:

```css-79elbk
<configuration>
   [...]
   <requiredForLanguages>php</requiredForLanguages>
</configuration>
```

{% endtab %}

{% tab title="GRADLE KOTLIN" %}
Using the MANIFEST attributes:

```css-79elbk
tasks.jar {
  manifest {
    attributes(
      mapOf(
        [...]
        "Plugin-RequiredForLanguages" to "php",
     ),
    )
  }
}
```

{% endtab %}
{% endtabs %}

### Going further <a href="#going-further" id="going-further"></a>

For more information, check the [Custom Java Rules 101](https://github.com/SonarSource/sonar-java/blob/7.16.0.30901/docs/CUSTOM_RULES_101.md), which goes into more detail on how to implement custom rules demonstrated in the Java domain.

## Related Pages <a href="#related-pages" id="related-pages"></a>

* [External Analyzer Reports](https://docs.sonarsource.com/sonarqube-server/analyzing-source-code/importing-external-issues/external-analyzer-reports) ([PHPStan](https://phpstan.org/), [Psalm](https://psalm.dev/))
* [overview](https://docs.sonarsource.com/sonarqube-server/analyzing-source-code/test-coverage/overview "mention")
* [adding-coding-rules](https://docs.sonarsource.com/sonarqube-server/extension-guide/adding-coding-rules "mention")
