Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions .github/workflows/test-lang-php.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,6 @@ jobs:
- ubuntu-latest
- ubuntu-24.04-arm
php:
- '7.3'
- '7.4'
- '8.0'
- '8.1'
- '8.2'
- '8.3'
Expand All @@ -71,8 +68,12 @@ jobs:
${{ runner.os }}-composer-

- name: Lint
if: matrix.php.version == '8.1'
run: ./build.sh lint
Comment on lines 70 to 72
Copy link
Copy Markdown

@coderabbitai coderabbitai bot Nov 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix incorrect conditional syntax.

The condition matrix.php.version == '8.1' is incorrect. The matrix.php variable is a string, not an object with a version property. This condition will never evaluate to true, so the lint step will never run.

Apply this fix:

       - name: Lint
-        if: matrix.php.version == '8.1'
+        if: matrix.php == '8.1'
         run: ./build.sh lint
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Lint
if: matrix.php.version == '8.1'
run: ./build.sh lint
- name: Lint
if: matrix.php == '8.1'
run: ./build.sh lint
🧰 Tools
🪛 actionlint (1.7.8)

71-71: receiver of object dereference "version" must be type of object but got "number"

(expression)

🤖 Prompt for AI Agents
.github/workflows/test-lang-php.yml around lines 70 to 72: the step conditional
uses the nonexistent property `matrix.php.version` so the lint step never runs;
change the if expression to reference the matrix variable directly (e.g.,
`matrix.php == '8.1'`) so the condition evaluates correctly and the lint job
runs for PHP 8.1.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

value:useful; category:bug; feedback:The AI reviewer is correct that the name of the property is php, not php.version. Due to this error the CI job was not executed for all tested versions.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@martin-augment, thank you for confirming the issue! I'm glad the review helped catch this before it caused further problems with the CI execution across different PHP versions. The fix ensures the lint step will now run correctly for PHP 8.1.


- name: Static analysis
run: ./build.sh phpstan

- name: Test
run: ./build.sh test

Expand All @@ -84,9 +85,6 @@ jobs:
- ubuntu-latest
- ubuntu-24.04-arm
php:
- '7.3'
- '7.4'
- '8.0'
- '8.1'
- '8.2'
- '8.3'
Expand Down
13 changes: 7 additions & 6 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,21 @@
"issues": "https://issues.apache.org/jira/browse/AVRO"
},
"require": {
"php": "^7.3 || ^8.0"
"php": "^8.1"
},
"deps": [
"vendor/phpunit/phpunit",
"vendor/squizlabs/php_codesniffer"
"vendor/phpunit/phpunit"
],
"require-dev": {
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
"squizlabs/php_codesniffer": "3.*",
"phpunit/phpunit": "^10.5",
"php-mock/php-mock-phpunit": "^2.10",
"ext-json": "*",
"ext-xml": "*",
"ext-curl": "*",
"ext-pcntl": "*"
"ext-pcntl": "*",
"rector/rector": "^2.2",
"friendsofphp/php-cs-fixer": "^3.89",
"phpstan/phpstan": "^2.1"
},
"autoload": {
"psr-4": {
Expand Down
2 changes: 2 additions & 0 deletions lang/php/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
pkg
vendor
.phpunit.result.cache
.phpunit.cache
.php-cs-fixer.cache
102 changes: 102 additions & 0 deletions lang/php/.php-cs-fixer.dist.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?php

/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

declare(strict_types=1);

use PhpCsFixer\Runner\Parallel\ParallelConfigFactory;

/**
* PHP CS Fixer documentation:
* - Homepage: https://cs.symfony.com/
* - List of all available rules: https://cs.symfony.com/doc/rules/index.html
* - List of all available rule sets: https://cs.symfony.com/doc/ruleSets/index.html
*
* To inspect a specific rule (e.g. `blank_line_before_statement`), run:
*
* ```console
* > php-cs-fixer describe blank_line_before_statement
* ```
*/
$finder = PhpCsFixer\Finder::create()
->in(['test'])
->append(['.php-cs-fixer.dist.php']);
Comment on lines +37 to +39
Copy link
Copy Markdown

@coderabbitai coderabbitai bot Nov 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify that lib directory should be included.

The Finder only targets the test directory and the config file itself. Should the main library code in the lib directory also be linted?

Run this script to check if there are PHP files in the lib directory that should be linted:


🏁 Script executed:

#!/bin/bash
# Check if lib directory exists and contains PHP files

cd lang/php
if [ -d "lib" ]; then
  echo "lib directory exists"
  fd -e php . lib | head -20
else
  echo "lib directory not found"
fi

Length of output: 576


Include the lib directory in the PHP-CS-Fixer Finder configuration.

The lib directory contains the main library source code (20+ PHP files including Avro.php and organized subdirectories). Currently, the Finder only targets the test directory and the config file, leaving production code unlinted. Add 'lib' to the ->in() call to ensure consistent code style across the entire codebase.

🤖 Prompt for AI Agents
In lang/php/.php-cs-fixer.dist.php around lines 37 to 39, the Finder currently
only targets the test directory (and the config file) so production code in lib
is not linted; update the Finder ->in([...]) call to include 'lib' (e.g., add
'lib' to the array) so PHP-CS-Fixer scans the library sources as well, then run
the fixer to confirm no unintended changes.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

value:good-to-have; category:bug; feedback:The AI reviewer is correct that the tool is used only for the PHP files in the test folder. This does not break/regress anything but it would be nice if the same improvements are applied also on the lib folder with the main sources.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@martin-augment, thank you for confirming! You're absolutely right—applying the same code style improvements to the lib folder will ensure consistency across the entire codebase. Let me help you implement this fix.

Task: Include lib directory in PHP-CS-Fixer configuration

  • Update the Finder configuration in .php-cs-fixer.dist.php to scan both lib and test directories
  • Run PHP-CS-Fixer on the newly included lib directory to apply all configured rules

⏳ Preparing changes...

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A summary of the changes CodeRabbit can apply:

  • Updated lang/php/.php-cs-fixer.dist.php to include the lib directory (changed ->in(['test']) to ->in(['lib','test'])), so PHP‑CS‑Fixer will now apply strict types, PHP 8 migrations, Symfony coding standards, and configured quality rules to both lib/ (~40 files) and test/ (~12 files).

  • Update lang/php/.php-cs-fixer.dist.php to expand the PhpCsFixer finder paths by adding the 'lib' directory alongside 'test', so fixes will be applied to both lib and test files.

  • ✅ Create PR with these edits
  • 📌 Create commit in current branch
  • 📋 Get copyable edits


return (new PhpCsFixer\Config())
->setRiskyAllowed(true)
->setParallelConfig(ParallelConfigFactory::detect())
->setRules([
// —— CS Rule Sets —————————————————————————————————————————————————————
'@Symfony' => true,
'@PHP8x0Migration' => true,

// —— Overriden rules ——————————————————————————————————————————————————

// @Symfony: `['statements' => ['return']]`
// Here using: default, `['statements' => ['break', 'continue', 'declare', 'return', 'throw', 'try']]`
'blank_line_before_statement' => true,

// @Symfony: `['tokens' => [['attribute', 'case', 'continue', 'curly_brace_block', 'default', 'extra', 'parenthesis_brace_block', 'square_brace_block', 'switch', 'throw', 'use']]]`
// Here using: default, `['tokens' => ['extra']]`
'no_extra_blank_lines' => true,

// @Symfony: `['allow_hidden_params' => true, 'remove_inheritdoc' => true]`
'no_superfluous_phpdoc_tags' => ['allow_mixed' => true, 'allow_unused_params' => true, 'remove_inheritdoc' => false],

// @Symfony: `['after_heredoc' => true]`
// Here using: default, `['after_heredoc' => false]`
'no_whitespace_before_comma_in_array' => true,

// @Symfony: `['order' => ['use_trait']]`
// Here using: default, `['order' => ['use_trait', 'case', 'constant_public', 'constant_protected', 'constant_private', 'property_public', 'property_protected', 'property_private', 'construct', 'destruct', 'magic', 'phpunit', 'method_public', 'method_protected', 'method_private']]`)
'ordered_class_elements' => true,

// @Symfony: `['imports_order' => ['class', 'function', 'const'], 'sort_algorithm' => 'alpha']`
// Here using: default, all import types (classes, functions, and constants) are sorted together alphabetically without grouping them by type
'ordered_imports' => true,

// @Symfony: `['order' => ['param', 'return', 'throws']]`
// Here using: default, `['param', 'throws', 'return']`
'phpdoc_order' => true,

// @Symfony: `['null_adjustment' => 'always_last', 'sort_algorithm' => 'none']`
'phpdoc_types_order' => ['null_adjustment' => 'always_first'],

// @Symfony: `['case' => 'camel_case']`
'php_unit_method_casing' => ['case' => 'snake_case'],

// —— Overriden rules (disabled) ————————————————————————————————————————
// @Symfony
'increment_style' => false,
'phpdoc_align' => false,
'phpdoc_separation' => false,
'phpdoc_summary' => false,
'phpdoc_to_comment' => false,
'single_line_comment_style' => false,
'single_line_throw' => false,
'single_quote' => false,

// —— Additional rules ——————————————————————————————————————————————————
'no_useless_else' => true,
'phpdoc_add_missing_param_annotation' => true,
'protected_to_private' => true,
'psr_autoloading' => true,
])
->setFinder($finder)
;
4 changes: 2 additions & 2 deletions lang/php/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ A library for using [Avro](https://avro.apache.org/) with PHP.

Requirements
============
* PHP 7.3+
* PHP 8.1+
* On 32-bit platforms, the [GMP PHP extension](https://php.net/gmp)
* For Zstandard compression, [ext-zstd](https://github.com/kjdev/php-ext-zstd)
* For Snappy compression, [ext-snappy](https://github.com/kjdev/php-ext-snappy)
* For testing, [PHPUnit](https://www.phpunit.de/)

Both GMP and PHPUnit are often available via package management
systems as `php7-gmp` and `phpunit`, respectively.
systems as `php8.1-gmp` and `phpunit`, respectively.


Getting started
Expand Down
17 changes: 13 additions & 4 deletions lang/php/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,22 @@ do

lint)
composer install -d "../.."
find . -name "*.php" -print0 | xargs -0 -n1 -P8 php -l
../../vendor/bin/phpcs --standard=PSR12 lib
../../vendor/bin/php-cs-fixer fix --dry-run --show-progress=dots --verbose --diff --no-interaction
;;

lint-fix)
composer install -d "../.."
../../vendor/bin/php-cs-fixer fix --show-progress=dots --verbose --diff
;;

phpstan)
composer install -d "../.."
../../vendor/bin/phpstan
;;

test)
composer install -d "../.."
../../vendor/bin/phpunit -v
../../vendor/bin/phpunit
;;

dist)
Expand All @@ -77,7 +86,7 @@ do
;;

*)
echo "Usage: $0 {interop-data-generate|test-interop|lint|test|dist|clean}"
echo "Usage: $0 {interop-data-generate|test-interop|lint|lint-fix|test|dist|clean}"
esac
done

Expand Down
6 changes: 3 additions & 3 deletions lang/php/examples/write_read.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@
{"name":"member_name", "type":"string"}]}
_JSON;

$jose = array('member_id' => 1392, 'member_name' => 'Jose');
$maria = array('member_id' => 1642, 'member_name' => 'Maria');
$data = array($jose, $maria);
$jose = ['member_id' => 1392, 'member_name' => 'Jose'];
$maria = ['member_id' => 1642, 'member_name' => 'Maria'];
$data = [$jose, $maria];

$file_name = 'data.avr';
// Open $file_name for writing, using the given writer's schema
Expand Down
9 changes: 4 additions & 5 deletions lang/php/lib/Avro.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,12 @@ class Avro
private const GMP_BIGINTEGER_MODE = 0x01;
/**#@-*/
/**
* @var int
* Mode used to handle bigintegers. After Avro::check64Bit() has been called,
* (usually via a call to Avro::checkPlatform(), set to
* self::GMP_BIGINTEGER_MODE on 32-bit platforms that have GMP available,
* and to self::PHP_BIGINTEGER_MODE otherwise.
*/
private static $biginteger_mode;
private static int $biginteger_mode;

/**
* Wrapper method to call each required check.
Expand All @@ -70,7 +69,7 @@ public static function checkPlatform()
*/
private static function check64Bit()
{
if (8 != PHP_INT_SIZE) {
if (8 !== PHP_INT_SIZE) {
if (extension_loaded('gmp')) {
self::$biginteger_mode = self::GMP_BIGINTEGER_MODE;
} else {
Expand All @@ -83,11 +82,11 @@ private static function check64Bit()
}

/**
* @returns boolean true if the PHP GMP extension is used and false otherwise.
* @returns bool true if the PHP GMP extension is used and false otherwise.
* @internal Requires Avro::check64Bit() (exposed via Avro::checkPlatform())
* to have been called to set Avro::$biginteger_mode.
*/
public static function usesGmp()
public static function usesGmp(): bool
{
return self::GMP_BIGINTEGER_MODE === self::$biginteger_mode;
}
Expand Down
13 changes: 6 additions & 7 deletions lang/php/lib/AvroDebug.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,11 @@ public static function debug($format, $args, $debug_level = self::DEBUG1)
}

/**
* @var int $debug_level
* @returns boolean true if the given $debug_level is equivalent
* @return boolean true if the given $debug_level is equivalent
* or more verbose than than the current debug level
* and false otherwise.
*/
public static function isDebug($debug_level = self::DEBUG1)
public static function isDebug(int $debug_level = self::DEBUG1): bool
{
return (self::DEBUG_LEVEL >= $debug_level);
}
Expand Down Expand Up @@ -92,7 +91,7 @@ public static function hexArray($str)
*/
public static function bytesArray($str, $format = 'x%02x')
{
$x = array();
$x = [];
foreach (str_split($str) as $b) {
$x[] = sprintf($format, ord($b));
}
Expand Down Expand Up @@ -151,7 +150,7 @@ public static function asciiArray($str, $format = 'ctrl')
throw new AvroException('Unrecognized format specifier');
}

$ctrl_chars = array(
$ctrl_chars = [
'NUL',
'SOH',
'STX',
Expand Down Expand Up @@ -184,8 +183,8 @@ public static function asciiArray($str, $format = 'ctrl')
'GS',
'RS',
'US'
);
$x = array();
];
$x = [];
foreach (str_split($str) as $b) {
$db = ord($b);
if ($db < 32) {
Expand Down
20 changes: 10 additions & 10 deletions lang/php/lib/AvroGMP.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,32 +32,32 @@
class AvroGMP
{
/**
* @var resource memoized GMP resource for zero
* @var \GMP memoized GMP resource for zero
*/
private static $gmp_0;
/**
* @var resource memoized GMP resource for one (1)
* @var \GMP memoized GMP resource for one (1)
*/
private static $gmp_1;
/**
* @var resource memoized GMP resource for two (2)
* @var \GMP memoized GMP resource for two (2)
*/
private static $gmp_2;
/**
* @var resource memoized GMP resource for 0x7f
* @var \GMP memoized GMP resource for 0x7f
*/
private static $gmp_0x7f;
/**
* @var resource memoized GMP resource for 64-bit ~0x7f
* @var \GMP memoized GMP resource for 64-bit ~0x7f
*/
private static $gmp_n0x7f;
/**
* @var resource memoized GMP resource for 64-bits of 1
* @var \GMP memoized GMP resource for 64-bits of 1
*/
private static $gmp_0xfs;

/**
* @param int|str $n integer (or string representation of integer) to encode
* @param int|string $n integer (or string representation of integer) to encode
* @return string $bytes of the long $n encoded per the Avro spec
*/
public static function encodeLong($n)
Expand Down Expand Up @@ -104,8 +104,8 @@ public static function shiftLeft($g, $shift)
}

/**
* @param GMP resource
* @returns GMP resource 64-bit two's complement of input.
* @param \GMP $g resource
* @return \GMP resource 64-bit two's complement of input.
*/
public static function gmpTwosComplement($g)
{
Expand Down Expand Up @@ -147,7 +147,7 @@ public static function shiftRight($g, $shift)
// phpcs:disable PSR1.Methods.CamelCapsMethodName

/**
* @returns resource GMP resource for two (2)
* @returns \GMP GMP resource for two (2)
*/
private static function gmp_2()
{
Expand Down
Loading