From e8222f336201f7f438cd424a200cd0b10e5ab9d4 Mon Sep 17 00:00:00 2001 From: Ibrahim BinAlshikh Date: Wed, 4 Mar 2026 01:35:17 +0300 Subject: [PATCH 1/5] feat: Added Support for Converting Public Props --- WebFiori/Json/Json.php | 39 ++++----- WebFiori/Json/JsonConverter.php | 81 +++++++++++++------ WebFiori/Json/JsonI.php | 26 ++++-- .../WebFiori/Tests/Json/JsonConverterTest.php | 41 ++++++++++ tests/WebFiori/Tests/ObjWithPublicProps.php | 15 ++++ 5 files changed, 152 insertions(+), 50 deletions(-) create mode 100644 tests/WebFiori/Tests/ObjWithPublicProps.php diff --git a/WebFiori/Json/Json.php b/WebFiori/Json/Json.php index 809e885..cc8b90d 100644 --- a/WebFiori/Json/Json.php +++ b/WebFiori/Json/Json.php @@ -358,26 +358,29 @@ public function addNumber(string $key, $value) { return true; } /** - * Adds an object to the JSON string. - * - * The object that will be added can implement the interface JsonI to make - * the generated JSON string customizable. Also, the object can be of - * type Json. If the given value is an object that does not implement the - * interface JsonI, or it is not of type Json, - * The method will try to extract object information based on its "getXxxxx()" public - * methods. Assuming that the object has 2 public methods with names - * getFirstProp() and getSecondProp(). - * In that case, the generated JSON will be on the format - * {"FirstProp":"prop-1","SecondProp":""}. - * This method also can be used to update the value of an existing property. - * + * Adds an object to the JSON data. + * + * The object is serialized using the following rules: + * + * This method can also be used to update the value of an existing property. + * * @param string $key The key value. - * + * * @param JsonI|Json|object $val The object that will be added. - * - * @return bool The method will return true if the object is added. - * If the key value is invalid string, the method will return false. - * + * + * @return bool True if the object is added, false if the key is invalid. + * */ public function addObject(string $key, &$val) { if (!$this->updateExisting($key, $val)) { diff --git a/WebFiori/Json/JsonConverter.php b/WebFiori/Json/JsonConverter.php index 97978f4..b7cacb9 100644 --- a/WebFiori/Json/JsonConverter.php +++ b/WebFiori/Json/JsonConverter.php @@ -11,10 +11,22 @@ namespace WebFiori\Json; /** - * A class to convert Json instance to it's JSON string representation. + * A class to convert objects and Json instances to their JSON string representation. + * + * The conversion of plain objects follows this order of precedence: + *
    + *
  1. If the object implements {@see JsonI}, its {@see JsonI::toJSON()} method is called.
  2. + *
  3. If the object is already an instance of {@see Json}, it is returned as-is.
  4. + *
  5. Otherwise, public getter methods (prefixed with 'get') are called and their return + * values are mapped to properties. The property name is derived by stripping the 'get' + * prefix (e.g. getFullName() becomes FullName). Methods that + * return false or null are skipped.
  6. + *
  7. Finally, all public properties are extracted via reflection and added to the JSON + * output. Unlike getter-based mapping, public properties with a null value are included.
  8. + *
* * @author Ibrahim - * + * */ class JsonConverter { private static $CRLF = "\r\n"; @@ -23,25 +35,31 @@ class JsonConverter { private static $TabSize = 0; private static $XmlClosingPool = []; /** - * Convert an object to Json object. - * - * Note that the properties which will be in the generated Json - * object will depend on the public 'get' methods of the object. - * The name of the properties will depend on the name of the method. For - * example, if the name of one of the methods is 'getFullName', then - * property name will be 'FullName'. - * - * @param object $obj The object that will be converted. - * - * @return Json + * Converts a plain PHP object to a {@see Json} instance. + * + * The conversion follows this order: + *
    + *
  1. If the object implements {@see JsonI}, its {@see JsonI::toJSON()} method is + * called and the result is returned directly.
  2. + *
  3. If the object is already an instance of {@see Json}, it is returned as-is.
  4. + *
  5. All public methods whose names start with 'get' are called. The portion of the + * method name after 'get' becomes the property name (e.g. getFullName() + * produces the key FullName). Methods returning false or null are + * skipped.
  6. + *
  7. All public properties are extracted via {@see \ReflectionClass} and added to + * the result. Properties with a null value are included; private and protected + * properties are ignored.
  8. + *
+ * + * @param object $obj The object to convert. + * + * @return Json A Json instance populated with the object's data. */ public static function objectToJson($obj) { if (is_subclass_of($obj, 'Webfiori\\Json\\JsonI')) { return $obj->toJSON(); - } else { - if ($obj instanceof Json) { - return $obj; - } + } else if ($obj instanceof Json) { + return $obj; } $methods = get_class_methods($obj); @@ -61,8 +79,18 @@ public static function objectToJson($obj) { } } } + restore_error_handler(); + $reflection = new \ReflectionClass($obj); + $publicProps = $reflection->getProperties(\ReflectionProperty::IS_PUBLIC); + + foreach ($publicProps as $prop) { + $name = $prop->getName(); + $value = $prop->getValue($obj); + $json->add($name, $value); + } + return $json; } /** @@ -330,13 +358,18 @@ private static function getNumberVal($val) { return $retVal; } /** - * - * @param object $probVal - * - * @param string $style - * - * @return string - * + * Converts an object value to its JSON string representation. + * + * If the value is not already a {@see Json} instance and does not implement + * {@see JsonI}, it is first passed through {@see self::objectToJson()} which + * maps public getter methods and public properties via reflection. + * + * @param object $probVal The object to convert. + * @param string $style The property naming style to apply. + * @param string $lettersCase The letter case to apply to property names. + * + * @return string JSON object string representation. + * * @since 1.0 */ private static function objToJson($probVal, string $style, string $lettersCase) { diff --git a/WebFiori/Json/JsonI.php b/WebFiori/Json/JsonI.php index 967072e..0840838 100644 --- a/WebFiori/Json/JsonI.php +++ b/WebFiori/Json/JsonI.php @@ -11,18 +11,28 @@ namespace WebFiori\Json; /** - * An interface for the objects that can be added to an instance of Json. - * @author Ibrahim + * Interface for objects that provide a custom JSON representation. + * + * Implementing this interface allows a class to control exactly how it is + * serialized when passed to {@see Json::addObject()} or + * {@see JsonConverter::objectToJson()}. When either of those methods encounters + * an object that implements this interface, they call {@see JsonI::toJSON()} + * instead of falling back to getter-method or reflection-based mapping. + * + * @author Ibrahim * @see Json + * @see JsonConverter */ interface JsonI { /** - * Returns an object of type Json. - * This method can be implemented by any class that will be added - * to any Json instance. It is used to customize the generated - * JSON string. - * - * @return Json An instance of Json. + * Returns a {@see Json} instance that represents the object. + * + * Implement this method to define which properties are included in the + * JSON output and how they are named. The returned instance will be used + * directly by {@see Json::addObject()} and {@see JsonConverter::objectToJson()}, + * bypassing getter-method scanning and reflection-based property extraction. + * + * @return Json A Json instance representing this object. */ public function toJSON() : Json; } diff --git a/tests/WebFiori/Tests/Json/JsonConverterTest.php b/tests/WebFiori/Tests/Json/JsonConverterTest.php index e874f26..3648e0e 100644 --- a/tests/WebFiori/Tests/Json/JsonConverterTest.php +++ b/tests/WebFiori/Tests/Json/JsonConverterTest.php @@ -5,6 +5,7 @@ use WebFiori\Json\Json; use WebFiori\Tests\Obj0; use WebFiori\Tests\Obj1; +use WebFiori\Tests\ObjWithPublicProps; use PHPUnit\Framework\TestCase; use WebFiori\Json\Property; use WebFiori\Json\JsonConverter; @@ -76,4 +77,44 @@ public function testPropertyToJsonXString01() { . ' world'."\r\n" . ''."\r\n", JsonConverter::propertyToJsonXString($prop, false)); } + + /** + * @test + */ + public function testObjectToJsonPublicPropsBasic() { + $obj = new \WebFiori\Tests\ObjWithPublicProps('Ibrahim', 30, true); + $json = JsonConverter::objectToJson($obj); + $this->assertTrue($json instanceof Json); + $this->assertTrue($json->hasKey('name')); + $this->assertTrue($json->hasKey('age')); + $this->assertTrue($json->hasKey('active')); + } + /** + * @test + */ + public function testObjectToJsonPublicPropsValues() { + $obj = new \WebFiori\Tests\ObjWithPublicProps('Ibrahim', 30, true); + $json = JsonConverter::objectToJson($obj); + $this->assertEquals('Ibrahim', $json->get('name')); + $this->assertEquals(30, $json->get('age')); + $this->assertEquals(true, $json->get('active')); + } + /** + * @test + */ + public function testObjectToJsonPrivatePropsNotIncluded() { + $obj = new \WebFiori\Tests\ObjWithPublicProps('Ibrahim', 30, true); + $json = JsonConverter::objectToJson($obj); + $this->assertFalse($json->hasKey('secret')); + } + /** + * @test + */ + public function testObjectToJsonPublicPropsNullValue() { + $obj = new \WebFiori\Tests\ObjWithPublicProps('Ibrahim', 30, true); + $obj->name = null; + $json = JsonConverter::objectToJson($obj); + $this->assertTrue($json->hasKey('name')); + $this->assertNull($json->get('name')); + } } diff --git a/tests/WebFiori/Tests/ObjWithPublicProps.php b/tests/WebFiori/Tests/ObjWithPublicProps.php new file mode 100644 index 0000000..e23a51f --- /dev/null +++ b/tests/WebFiori/Tests/ObjWithPublicProps.php @@ -0,0 +1,15 @@ +name = $name; + $this->age = $age; + $this->active = $active; + } +} From 8798259d5f27b1bfa82acbbaffb816c50b76f98d Mon Sep 17 00:00:00 2001 From: Ibrahim BinAlshikh Date: Wed, 4 Mar 2026 01:42:13 +0300 Subject: [PATCH 2/5] chore: Updated Composer File - Added CS Fixer - Added `ext-json` as Requred - Change `test-10` to `test10` --- composer.json | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index def2da4..cd73c7c 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,8 @@ ], "license": "MIT", "require": { - "php": ">=8.0" + "php": ">=8.1", + "ext-json": "*" }, "autoload": { "psr-4": { @@ -24,9 +25,11 @@ }, "scripts": { "test": "phpunit --configuration tests/phpunit.xml", - "test-10": "phpunit --configuration tests/phpunit10.xml" + "test10": "phpunit --configuration tests/phpunit10.xml", + "fix-cs": "php-cs-fixer fix --config=php_cs.php.dist" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^10.0", + "friendsofphp/php-cs-fixer": "^3.92" } -} +} From bc4d7b292e3e0e67acf23be9162a7fda6df2fe43 Mon Sep 17 00:00:00 2001 From: Ibrahim BinAlshikh Date: Wed, 4 Mar 2026 01:57:59 +0300 Subject: [PATCH 3/5] docs: Updated Documentation of Library --- README.md | 505 +++++++++------------------- examples/01-basic-usage.php | 16 + examples/02-arrays.php | 11 + examples/03-object-with-jsoni.php | 23 ++ examples/04-object-auto-mapping.php | 26 ++ examples/05-naming-styles.php | 16 + examples/06-decode-and-read.php | 20 ++ examples/07-jsonx.php | 12 + examples/README.md | 17 + examples/basic-usage.php | 35 -- examples/sample.json | 5 + examples/use-with-arrays.php | 33 -- examples/use-with-classes-2.php | 43 --- examples/use-with-classes.php | 55 --- 14 files changed, 302 insertions(+), 515 deletions(-) create mode 100644 examples/01-basic-usage.php create mode 100644 examples/02-arrays.php create mode 100644 examples/03-object-with-jsoni.php create mode 100644 examples/04-object-auto-mapping.php create mode 100644 examples/05-naming-styles.php create mode 100644 examples/06-decode-and-read.php create mode 100644 examples/07-jsonx.php create mode 100644 examples/README.md delete mode 100644 examples/basic-usage.php create mode 100644 examples/sample.json delete mode 100644 examples/use-with-arrays.php delete mode 100644 examples/use-with-classes-2.php delete mode 100644 examples/use-with-classes.php diff --git a/README.md b/README.md index 9dda357..af879b2 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # WebFiori Json -A helper class library for creating JSON or JSONx strings in PHP. It can be used to create well-formatted JSON strings from any variable type (strings, numbers, booleans, arrays, and even objects). +A PHP library for creating and parsing JSON and JSONx strings. Supports all PHP scalar types, arrays, and objects with flexible property naming styles.

@@ -18,41 +18,30 @@ A helper class library for creating JSON or JSONx strings in PHP. It can be used

## Table of Contents -* [What is JSON?](#what-is-json) * [Features](#features) * [Supported PHP Versions](#supported-php-versions) * [Installation](#installation) * [Basic Usage](#basic-usage) - * [Example](#example) - * [Using the Constructor](#using-the-constructor) -* [Converting Properties Case](#converting-properties-case) - * [Available Styles](#available-styles) - * [Letter Case Options](#letter-case-options) -* [Reading From Files](#reading-from-files) +* [Working With Arrays](#working-with-arrays) * [Working With Objects](#working-with-objects) * [Using JsonI Interface](#using-jsoni-interface) * [Auto-Mapping Objects](#auto-mapping-objects) -* [Decoding JSON String](#decoding-json-string) -* [Storing Output](#storing-output) -* [Working With Arrays](#working-with-arrays) - * [Arrays as Objects](#arrays-as-objects) +* [Property Naming Styles](#property-naming-styles) +* [Decoding JSON](#decoding-json) +* [Saving to File](#saving-to-file) * [JSONx](#jsonx) * [Error Handling](#error-handling) * [API Reference](#api-reference) -## What is JSON? - -According to [json.org](https://www.json.org/json-en.html), JSON is a data exchange format which is based partially on JavaScript. It is easy for humans to read and for machines to understand. JSON data is represented as pairs of keys and values. - ## Features -* Support for creating well-formatted JSON with proper indentation and escaping -* Support for creating [JSONx](https://www.ibm.com/docs/en/datapower-gateways/10.0.1?topic=20-jsonx) (XML representation of JSON) -* Ability to decode JSON strings and convert them to `Json` objects -* Ability to read JSON files and map JSON values to PHP data types -* Ability to manipulate JSON properties as needed -* Support for different property naming styles (camelCase, kebab-case, snake_case) -* Support for different letter cases (same, upper, lower) -* Customizable object serialization through the `JsonI` interface +* Create well-formatted JSON strings from any PHP value (scalars, arrays, objects) +* Decode JSON strings and files into `Json` objects +* Flexible property naming styles: `camelCase`, `kebab-case`, `snake_case`, or `none` +* Letter case control: `same`, `upper`, `lower` +* Custom object serialization via the `JsonI` interface +* Auto-mapping of plain objects via public getter methods and public properties +* [JSONx](https://www.ibm.com/docs/en/datapower-gateways/10.0.1?topic=20-jsonx) output (XML representation of JSON) +* Save JSON output directly to a file ## Supported PHP Versions | Build Status | @@ -63,7 +52,6 @@ According to [json.org](https://www.json.org/json-en.html), JSON is a data excha | | ## Installation -If you are using composer to manage your dependencies, then it is possible to install the library by including the entry `"webfiori/jsonx":"*"` in the `require` section of your `composer.json` file to install the latest release: ```json { @@ -73,208 +61,100 @@ If you are using composer to manage your dependencies, then it is possible to in } ``` -Alternatively, you can install a specific version: +Or for a specific version: ```json { "require": { - "webfiori/jsonx": "^1.0" + "webfiori/jsonx": "^3.0" } } ``` -Another way to include the library is by going to [releases](https://github.com/WebFiori/json/releases) and downloading the latest release, then extracting the compressed file content and adding it to your include directory. - -## Basic Usage -The process of using the classes is very simple. What you have to do is the following steps: - - * Import (or include) the class `Json` from the namespace `WebFiori\Json` - * Create an instance of the class - * Add data as needed using the various `add` methods - * Output the object using `echo` command or any similar one - -### Example -The following code shows a very simple usage example: - -```php -//load the class "Json" -require_once 'vendor/autoload.php'; // If using Composer -// OR require_once 'path/to/WebFiori/Json/Json.php'; // If manually installed - -use WebFiori\Json\Json; - -//initialize an object of the class Json -$j = new Json(); - -//add a number attribute -$j->addNumber('my-number', 34); - -//add a boolean with 'false' as its value. -$j->addBoolean('my-boolean', false); - -//add a string -$j->addString('a-string', 'Hello, I\'m Json! I like "JSON". '); - -header('content-type:application/json'); - -// Output the JSON string -echo $j; -``` - -The output of the code will be: +Then run: -```json -{ - "my-number":34, - "my-boolean":false, - "a-string":"Hello, I'm Json! I like \"JSON\". " -} +```bash +composer install ``` -### Using the Constructor - -You can also add data directly using the constructor by passing an associative array: +## Basic Usage ```php use WebFiori\Json\Json; -$jsonObj = new Json([ - 'first-name' => 'Ibrahim', - 'last-name' => 'BinAlshikh', - 'age' => 26, - 'is-married' => true, - 'mobile-number' => null +$json = new Json([ + 'name' => 'Ibrahim', + 'age' => 30, + 'married' => false, + 'score' => 9.5, + 'notes' => null, ]); -echo $jsonObj; +echo $json; ``` -The JSON output of this code will be: +Output: ```json -{ - "first-name":"Ibrahim", - "last-name":"BinAlshikh", - "age":26, - "is-married":true, - "mobile-number":null -} +{"name":"Ibrahim","age":30,"married":false,"score":9.5,"notes":null} ``` -## Converting Properties Case - -The library supports different property naming styles and letter cases. You can set these when creating a Json object or change them later. - -### Available Styles - -The following property naming styles are supported: - -* `none`: Keep the property names as they are provided -* `camel`: Convert property names to camelCase -* `kebab`: Convert property names to kebab-case -* `snake`: Convert property names to snake_case - -### Letter Case Options - -The following letter case options are available: - -* `same`: Keep the letter case as provided -* `upper`: Convert all letters to uppercase -* `lower`: Convert all letters to lowercase - -Example: +You can also build the object incrementally using the `add*()` methods: ```php -use WebFiori\Json\Json; - -// Set style and case in constructor -$json = new Json([], 'camel', 'lower'); - -// Add properties -$json->add('first-name', 'Ibrahim'); -$json->add('last-name', 'BinAlshikh'); +$json = new Json(); +$json->addString('name', 'Ibrahim'); +$json->addNumber('age', 30); +$json->addBoolean('married', false); +$json->addNull('notes'); echo $json; ``` -Output: +## Working With Arrays -```json -{ - "firstname":"Ibrahim", - "lastname":"BinAlshikh" -} -``` +```php +$json = new Json(); -You can also change the style after creating the object: +// Indexed array +$json->addArray('tags', ['php', 'json', 'api']); + +// Associative array represented as a JSON object +$json->addArray('address', ['city' => 'Riyadh', 'country' => 'SA'], true); -```php -$json->setPropsStyle('snake', 'upper'); echo $json; ``` Output: ```json -{ - "FIRST_NAME":"Ibrahim", - "LAST_NAME":"BinAlshikh" -} -``` - -## Reading From Files - -The library provides a static method to read JSON data from files: - -```php -use WebFiori\Json\Json; - -try { - $jsonObj = Json::fromJsonFile('/path/to/file.json'); - - // Access properties - $value = $jsonObj->get('propertyName'); - - echo $value; -} catch (\WebFiori\Json\JsonException $ex) { - echo 'Error: ' . $ex->getMessage(); -} +{"tags":["php","json","api"],"address":{"city":"Riyadh","country":"SA"}} ``` ## Working With Objects ### Using JsonI Interface -For custom object serialization, you can implement the `JsonI` interface: +Implement `JsonI` to fully control how an object is serialized: ```php use WebFiori\Json\Json; use WebFiori\Json\JsonI; -class Person implements JsonI { - private $firstName; - private $lastName; - private $age; - - public function __construct($firstName, $lastName, $age) { - $this->firstName = $firstName; - $this->lastName = $lastName; - $this->age = $age; - } - +class User implements JsonI { + public function __construct( + private string $username, + private string $email + ) {} + public function toJSON(): Json { - $json = new Json(); - $json->addString('first-name', $this->firstName); - $json->addString('last-name', $this->lastName); - $json->addNumber('age', $this->age); - - return $json; + return new Json(['username' => $this->username, 'email' => $this->email]); } } $json = new Json(); -$person = new Person('Ibrahim', 'BinAlshikh', 30); -$json->addObject('person', $person); +$user = new User('ibrahim', 'ibrahim@example.com'); +$json->addObject('user', $user); echo $json; ``` @@ -282,41 +162,34 @@ echo $json; Output: ```json -{ - "person":{ - "first-name":"Ibrahim", - "last-name":"BinAlshikh", - "age":30 - } -} +{"user":{"username":"ibrahim","email":"ibrahim@example.com"}} ``` ### Auto-Mapping Objects -If an object doesn't implement the `JsonI` interface, the library will try to map its public getter methods: +For objects that don't implement `JsonI`, the library maps them automatically using two sources: + +1. **Public getter methods** — any method prefixed with `get` is called and its return value is added. The property name is the method name with `get` stripped (e.g. `getName()` → `Name`). Methods returning `null` or `false` are skipped. +2. **Public properties** — extracted via reflection and added as-is, including those with a `null` value. ```php -class User { - private $username; - private $email; - - public function __construct($username, $email) { - $this->username = $username; - $this->email = $email; - } - - public function getUsername() { - return $this->username; - } - - public function getEmail() { - return $this->email; +class Product { + public string $sku = 'ABC-001'; // added via reflection + private string $name; + private float $price; + + public function __construct(string $name, float $price) { + $this->name = $name; + $this->price = $price; } + + public function getName(): string { return $this->name; } // → "Name" + public function getPrice(): float { return $this->price; } // → "Price" } $json = new Json(); -$user = new User('ibrahimBin', 'ibrahim@example.com'); -$json->addObject('user', $user); +$product = new Product('Keyboard', 49.99); +$json->addObject('product', $product); echo $json; ``` @@ -324,141 +197,76 @@ echo $json; Output: ```json -{ - "user":{ - "Username":"ibrahimBin", - "Email":"ibrahim@example.com" - } -} +{"product":{"Name":"Keyboard","Price":49.99,"sku":"ABC-001"}} ``` -## Decoding JSON String - -You can decode a JSON string into a `Json` object: +## Property Naming Styles -```php -use WebFiori\Json\Json; - -$jsonString = '{"name":"Ibrahim","age":30,"city":"Riyadh"}'; - -try { - $jsonObj = Json::decode($jsonString); - - // Access properties - echo $jsonObj->get('name'); // Outputs: Ibrahim - echo $jsonObj->get('age'); // Outputs: 30 - echo $jsonObj->get('city'); // Outputs: Riyadh -} catch (\WebFiori\Json\JsonException $ex) { - echo 'Error: ' . $ex->getMessage(); -} -``` - -## Storing Output +Four naming styles are supported: `none` (default), `camel`, `snake`, `kebab`. +Three letter cases are supported: `same` (default), `upper`, `lower`. -You can save the JSON output to a file: +Set them in the constructor or change them later with `setPropsStyle()`: ```php -use WebFiori\Json\Json; +$data = ['first-name' => 'Ibrahim', 'last-name' => 'Al-Shikh']; -$json = new Json([ - 'name' => 'Ibrahim', - 'age' => 30, - 'city' => 'Riyadh' -]); +echo new Json($data, 'none') . "\n"; // {"first-name":"Ibrahim","last-name":"Al-Shikh"} +echo new Json($data, 'camel') . "\n"; // {"firstName":"Ibrahim","lastName":"Al-Shikh"} +echo new Json($data, 'snake') . "\n"; // {"first_name":"Ibrahim","last_name":"Al-Shikh"} +echo new Json($data, 'kebab') . "\n"; // {"first-name":"Ibrahim","last-name":"Al-Shikh"} -try { - $json->toJsonFile('data', '/path/to/directory', true); - // This will create /path/to/directory/data.json - - echo 'File saved successfully!'; -} catch (\WebFiori\Json\JsonException $ex) { - echo 'Error: ' . $ex->getMessage(); -} +// Change style after construction +$json = new Json($data); +$json->setPropsStyle('snake', 'upper'); +echo $json . "\n"; // {"FIRST_NAME":"Ibrahim","LAST_NAME":"Al-Shikh"} ``` -## Working With Arrays +## Decoding JSON -You can add arrays to your JSON object: +Decode a JSON string directly: ```php -use WebFiori\Json\Json; - -$json = new Json(); - -// Simple array -$json->addArray('numbers', [1, 2, 3, 4, 5]); +$json = Json::decode('{"name":"Ibrahim","age":30}'); -// Array of objects -$json->addArray('users', [ - ['name' => 'Ibrahim', 'age' => 30], - ['name' => 'Jane', 'age' => 25], - ['name' => 'Bob', 'age' => 40] -]); - -echo $json; +echo $json->get('name'); // Ibrahim +echo $json->get('age'); // 30 ``` -Output: +Read from a file: -```json -{ - "numbers":[1,2,3,4,5], - "users":[ - {"name":"Ibrahim","age":30}, - {"name":"Jane","age":25}, - {"name":"Bob","age":40} - ] +```php +try { + $json = Json::fromJsonFile('/path/to/file.json'); + echo $json->get('someKey'); +} catch (\WebFiori\Json\JsonException $e) { + echo 'Error: ' . $e->getMessage(); } ``` -### Arrays as Objects - -You can also represent arrays as objects: +## Saving to File ```php -use WebFiori\Json\Json; - -$json = new Json(); +$json = new Json(['name' => 'Ibrahim', 'age' => 30]); -$json->addArray('data', [ - 'name' => 'Ibrahim', - 'age' => 30, - 'skills' => ['PHP', 'JavaScript', 'Python'] -], true); // true means represent as object - -echo $json; -``` - -Output: - -```json -{ - "data":{ - "name":"Ibrahim", - "age":30, - "skills":["PHP","JavaScript","Python"] - } +try { + $json->toJsonFile('data', '/path/to/directory', true); + // Creates /path/to/directory/data.json +} catch (\WebFiori\Json\JsonException $e) { + echo 'Error: ' . $e->getMessage(); } ``` ## JSONx -JSONx is an IBM standard format that represents JSON as XML. The library supports converting JSON to JSONx: +[JSONx](https://www.ibm.com/docs/en/datapower-gateways/10.0.1?topic=20-jsonx) is an IBM standard that represents JSON as XML: ```php -use WebFiori\Json\Json; - $json = new Json([ - 'name' => 'Ibrahim', - 'age' => 30, + 'name' => 'Ibrahim', + 'age' => 30, 'isEmployed' => true, - 'address' => [ - 'city' => 'Riyadh', - 'country' => 'Saudi Arabia' - ] ]); -// Output as JSONx echo $json->toJSONxString(); ``` @@ -466,67 +274,66 @@ Output: ```xml - - Ibrahim - 30 - true - - Riyadh - Saudi Arabia - + + Ibrahim + + + 30 + + + true + ``` ## Error Handling -The library uses the `JsonException` class for error handling: +All errors throw `\WebFiori\Json\JsonException`: ```php -use WebFiori\Json\Json; - try { - // Attempt to decode invalid JSON - $jsonObj = Json::decode('{invalid json}'); -} catch (\WebFiori\Json\JsonException $ex) { - echo 'Error code: ' . $ex->getCode() . "\n"; - echo 'Error message: ' . $ex->getMessage(); + $json = Json::decode('{invalid json}'); +} catch (\WebFiori\Json\JsonException $e) { + echo 'Error code: ' . $e->getCode() . "\n"; + echo 'Error message: ' . $e->getMessage() . "\n"; } ``` ## API Reference -### Main Classes - -- **Json**: The main class for creating and manipulating JSON data -- **JsonConverter**: Handles conversion between JSON and other formats -- **Property**: Represents a property in a JSON object -- **CaseConverter**: Utility for converting between different naming styles -- **JsonI**: Interface for objects that can be converted to JSON -- **JsonException**: Exception class for JSON-related errors -- **JsonTypes**: Constants for JSON data types - -### Key Methods - -#### Json Class -- `__construct(array $initialData = [], ?string $propsStyle = '', ?string $lettersCase = '', bool $isFormatted = false)` -- `add(string $key, $value, $arrayAsObj = false): bool` -- `addString(string $key, $val): bool` -- `addNumber(string $key, $value): bool` -- `addBoolean($key, $val = true): bool` -- `addNull(string $key): bool` -- `addArray(string $key, $value, $asObject = false): bool` -- `addObject(string $key, &$val): bool` -- `get($key): mixed` -- `hasKey($key): bool` -- `remove($keyName): ?Property` -- `setPropsStyle(string $style, string $lettersCase = 'same'): void` -- `setIsFormatted($bool): void` -- `toJSONString(): string` -- `toJSONxString(): string` -- `toJsonFile(string $fileName, string $path, bool $override = false): void` - -#### Static Methods -- `Json::decode($jsonStr): Json` -- `Json::fromJsonFile($pathToJsonFile): Json` +### Classes + +| Class | Description | +|-------|-------------| +| `Json` | Main class for building and reading JSON data | +| `JsonI` | Interface for custom object serialization | +| `JsonConverter` | Handles serialization to JSON and JSONx strings | +| `Property` | Represents a single JSON property | +| `CaseConverter` | Converts property names between naming styles | +| `JsonTypes` | Constants for JSON data types | +| `JsonException` | Exception thrown on JSON errors | + +### Key Methods — `Json` + +| Method | Description | +|--------|-------------| +| `add(string $key, mixed $value, bool $arrayAsObj = false): bool` | Add any value | +| `addString(string $key, string $val): bool` | Add a string | +| `addNumber(string $key, int\|float $value): bool` | Add a number | +| `addBoolean(string $key, bool $val = true): bool` | Add a boolean | +| `addNull(string $key): bool` | Add a null value | +| `addArray(string $key, array $value, bool $asObject = false): bool` | Add an array | +| `addObject(string $key, object &$val): bool` | Add an object | +| `get(string $key): mixed` | Get a property value | +| `hasKey(string $key): bool` | Check if a key exists | +| `remove(string $key): ?Property` | Remove a property | +| `setPropsStyle(string $style, string $lettersCase = 'same'): void` | Change naming style | +| `setIsFormatted(bool $bool): void` | Toggle formatted output | +| `toJSONString(): string` | Get JSON string | +| `toJSONxString(): string` | Get JSONx string | +| `toJsonFile(string $fileName, string $path, bool $override = false): void` | Save to file | +| `Json::decode(string $jsonStr): Json` | Decode a JSON string | +| `Json::fromJsonFile(string $path): Json` | Load from a JSON file | diff --git a/examples/01-basic-usage.php b/examples/01-basic-usage.php new file mode 100644 index 0000000..ec04d67 --- /dev/null +++ b/examples/01-basic-usage.php @@ -0,0 +1,16 @@ + 'Ibrahim', + 'age' => 30, + 'married' => false, + 'score' => 9.5, + 'notes' => null, +]); + +echo $json . "\n"; +// {"name":"Ibrahim","age":30,"married":false,"score":9.5,"notes":null} diff --git a/examples/02-arrays.php b/examples/02-arrays.php new file mode 100644 index 0000000..08854cf --- /dev/null +++ b/examples/02-arrays.php @@ -0,0 +1,11 @@ +addArray('tags', ['php', 'json', 'api']); +$json->addArray('address', ['city' => 'Riyadh', 'country' => 'SA'], true); // true = as object + +echo $json . "\n"; +// {"tags":["php","json","api"],"address":{"city":"Riyadh","country":"SA"}} diff --git a/examples/03-object-with-jsoni.php b/examples/03-object-with-jsoni.php new file mode 100644 index 0000000..9e72367 --- /dev/null +++ b/examples/03-object-with-jsoni.php @@ -0,0 +1,23 @@ + $this->username, 'email' => $this->email]); + } +} + +$json = new Json(); +$user = new User('ibrahim', 'ibrahim@example.com'); +$json->addObject('user', $user); + +echo $json . "\n"; +// {"user":{"username":"ibrahim","email":"ibrahim@example.com"}} diff --git a/examples/04-object-auto-mapping.php b/examples/04-object-auto-mapping.php new file mode 100644 index 0000000..73f3d55 --- /dev/null +++ b/examples/04-object-auto-mapping.php @@ -0,0 +1,26 @@ +name = $name; + $this->price = $price; + } + + public function getName(): string { return $this->name; } + public function getPrice(): float { return $this->price; } +} + +$json = new Json(); +$product = new Product('Keyboard', 49.99); +$json->addObject('product', $product); + +echo $json . "\n"; +// {"product":{"Name":"Keyboard","Price":49.99,"sku":"ABC-001"}} +// ^ getters produce "Name"/"Price", public property adds "sku" diff --git a/examples/05-naming-styles.php b/examples/05-naming-styles.php new file mode 100644 index 0000000..0598724 --- /dev/null +++ b/examples/05-naming-styles.php @@ -0,0 +1,16 @@ + 'Ibrahim', 'last-name' => 'Al-Shikh']; + +echo new Json($data, 'none') . "\n"; // {"first-name":"Ibrahim","last-name":"Al-Shikh"} +echo new Json($data, 'camel') . "\n"; // {"firstName":"Ibrahim","lastName":"Al-Shikh"} +echo new Json($data, 'snake') . "\n"; // {"first_name":"Ibrahim","last_name":"Al-Shikh"} +echo new Json($data, 'kebab') . "\n"; // {"first-name":"Ibrahim","last-name":"Al-Shikh"} + +// Change style after construction + apply upper case +$json = new Json($data); +$json->setPropsStyle('snake', 'upper'); +echo $json . "\n"; // {"FIRST_NAME":"Ibrahim","LAST_NAME":"Al-Shikh"} diff --git a/examples/06-decode-and-read.php b/examples/06-decode-and-read.php new file mode 100644 index 0000000..4bc736e --- /dev/null +++ b/examples/06-decode-and-read.php @@ -0,0 +1,20 @@ +get('name') . "\n"; // Ibrahim +echo $json->get('age') . "\n"; // 30 + +// Read from file +try { + $json = Json::fromJsonFile(__DIR__ . '/sample.json'); + echo $json->get('product') . "\n"; // Keyboard + echo $json->get('price') . "\n"; // 49.99 + echo ($json->get('inStock') ? 'true' : 'false') . "\n"; // true +} catch (JsonException $e) { + echo 'Error: ' . $e->getMessage() . "\n"; +} diff --git a/examples/07-jsonx.php b/examples/07-jsonx.php new file mode 100644 index 0000000..de3f00a --- /dev/null +++ b/examples/07-jsonx.php @@ -0,0 +1,12 @@ + 'Ibrahim', + 'age' => 30, + 'isEmployed' => true, +]); + +echo $json->toJSONxString() . "\n"; diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..f4ae564 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,17 @@ +# Examples + +| File | What it shows | +|------|---------------| +| [01-basic-usage.php](01-basic-usage.php) | Constructor init, scalar types, `echo` output | +| [02-arrays.php](02-arrays.php) | Indexed arrays, associative arrays as objects | +| [03-object-with-jsoni.php](03-object-with-jsoni.php) | Custom serialization via the `JsonI` interface | +| [04-object-auto-mapping.php](04-object-auto-mapping.php) | Auto-mapping via public getters and public properties | +| [05-naming-styles.php](05-naming-styles.php) | `camel` / `snake` / `kebab` / `none` styles + letter case | +| [06-decode-and-read.php](06-decode-and-read.php) | Decoding JSON strings and reading from files | +| [07-jsonx.php](07-jsonx.php) | Converting JSON to JSONx (XML) format | + +Run any example from the project root: + +```bash +php examples/01-basic-usage.php +``` diff --git a/examples/basic-usage.php b/examples/basic-usage.php deleted file mode 100644 index aa8b4f6..0000000 --- a/examples/basic-usage.php +++ /dev/null @@ -1,35 +0,0 @@ -addNumber('my-number', 34); - -//add a boolean with 'false' as its value. -$j->addBoolean('my-boolean', false); - -//add a string -$j->addString('a-string', 'Hello, I\'m JsonX! I like "JSON". '); - -header('content-type:application/json'); -/* -send back the generated json string. -The output of the code will be like that: -{ - "my-number":34, - "my-boolean":false, - "my-number":"Hello, I'm JsonX! I like \"json\". ", -} -*/ -echo $j; diff --git a/examples/sample.json b/examples/sample.json new file mode 100644 index 0000000..3b5bc81 --- /dev/null +++ b/examples/sample.json @@ -0,0 +1,5 @@ +{ + "product": "Keyboard", + "price": 49.99, + "inStock": true +} diff --git a/examples/use-with-arrays.php b/examples/use-with-arrays.php deleted file mode 100644 index 5764f35..0000000 --- a/examples/use-with-arrays.php +++ /dev/null @@ -1,33 +0,0 @@ - 'Ibrahim',100, - 'age' => '25','sex' => 'M',true,false -]; - -//add the array as is -$j->add('basic-array', $arr); - -//adding the array as object -$j->addArray('basic-array-as-object', $arr,true); - -//adding the array as is -$j->add('complicated-array', $arr2); - -//adding the array as object -$j->addArray('complicated-array-as-object', $arr2,true); -echo $j; diff --git a/examples/use-with-classes-2.php b/examples/use-with-classes-2.php deleted file mode 100644 index fc18edf..0000000 --- a/examples/use-with-classes-2.php +++ /dev/null @@ -1,43 +0,0 @@ -email; - } - public function getUserName() { - return $this->username; - } - - public function setEmail($email) { - $this->email = $email; - } - public function setUsername($username) { - $this->username = $username; - } -} - -$user = new User(); -$user->setEmail('example@example.com'); -$user->setUsername('Warrior Vx'); -$json = new Json(); -$json->addObject('user', $user); -header('content-type:application/json'); -echo $json; diff --git a/examples/use-with-classes.php b/examples/use-with-classes.php deleted file mode 100644 index 973217b..0000000 --- a/examples/use-with-classes.php +++ /dev/null @@ -1,55 +0,0 @@ -username; - } - - public function setEmail($email) { - $this->email = $email; - } - public function setUsername($username) { - $this->username = $username; - } - - //this function is from the interface JsonI - // it must return JsonX object - public function toJSON() { - $retVal = new Json(); - $retVal->addString('username', $this->username); - $retVal->addString('email', $this->email); - - return $retVal; - } -} -$user = new User(); -$user->setEmail('example@example.com'); -$user->setUsername('Warrior Vx'); - -$json = new JsonX(); -$json->addBoolean('my-boolean'); -$json->addObject('user', $user); - -//adding arrays -$json->addArray('my-arr', [1,2,"hello",["nested array"]]); - -header('content-type:application/json'); -//display json object in the browser. -echo $json; From 4e49727604b5b39418a4d6994f8266694a078d17 Mon Sep 17 00:00:00 2001 From: Ibrahim BinAlshikh Date: Wed, 4 Mar 2026 02:04:08 +0300 Subject: [PATCH 4/5] chore: Run CS Fixer --- WebFiori/Json/CaseConverter.php | 1 + WebFiori/Json/Json.php | 2 ++ WebFiori/Json/JsonConverter.php | 3 ++- WebFiori/Json/JsonException.php | 1 + WebFiori/Json/JsonI.php | 1 + WebFiori/Json/JsonTypes.php | 1 + WebFiori/Json/Property.php | 1 + examples/01-basic-usage.php | 13 +++++++------ examples/02-arrays.php | 5 +++-- examples/03-object-with-jsoni.php | 8 +++++--- examples/04-object-auto-mapping.php | 15 ++++++++++----- examples/05-naming-styles.php | 13 +++++++------ examples/06-decode-and-read.php | 17 +++++++++-------- examples/07-jsonx.php | 9 +++++---- php_cs.php.dist | 2 +- 15 files changed, 56 insertions(+), 36 deletions(-) diff --git a/WebFiori/Json/CaseConverter.php b/WebFiori/Json/CaseConverter.php index aa5ce49..c06337e 100644 --- a/WebFiori/Json/CaseConverter.php +++ b/WebFiori/Json/CaseConverter.php @@ -1,4 +1,5 @@ getProperties(\ReflectionProperty::IS_PUBLIC); - + foreach ($publicProps as $prop) { $name = $prop->getName(); $value = $prop->getValue($obj); diff --git a/WebFiori/Json/JsonException.php b/WebFiori/Json/JsonException.php index 0a22d48..47305de 100644 --- a/WebFiori/Json/JsonException.php +++ b/WebFiori/Json/JsonException.php @@ -1,4 +1,5 @@ 'Ibrahim', - 'age' => 30, + 'name' => 'Ibrahim', + 'age' => 30, 'married' => false, - 'score' => 9.5, - 'notes' => null, + 'score' => 9.5, + 'notes' => null, ]); -echo $json . "\n"; +echo $json."\n"; // {"name":"Ibrahim","age":30,"married":false,"score":9.5,"notes":null} diff --git a/examples/02-arrays.php b/examples/02-arrays.php index 08854cf..cfaa367 100644 --- a/examples/02-arrays.php +++ b/examples/02-arrays.php @@ -1,5 +1,6 @@ addArray('tags', ['php', 'json', 'api']); $json->addArray('address', ['city' => 'Riyadh', 'country' => 'SA'], true); // true = as object -echo $json . "\n"; +echo $json."\n"; // {"tags":["php","json","api"],"address":{"city":"Riyadh","country":"SA"}} diff --git a/examples/03-object-with-jsoni.php b/examples/03-object-with-jsoni.php index 9e72367..05586dc 100644 --- a/examples/03-object-with-jsoni.php +++ b/examples/03-object-with-jsoni.php @@ -1,5 +1,6 @@ $this->username, 'email' => $this->email]); @@ -19,5 +21,5 @@ public function toJSON(): Json { $user = new User('ibrahim', 'ibrahim@example.com'); $json->addObject('user', $user); -echo $json . "\n"; +echo $json."\n"; // {"user":{"username":"ibrahim","email":"ibrahim@example.com"}} diff --git a/examples/04-object-auto-mapping.php b/examples/04-object-auto-mapping.php index 73f3d55..0d8ac24 100644 --- a/examples/04-object-auto-mapping.php +++ b/examples/04-object-auto-mapping.php @@ -1,5 +1,6 @@ name = $name; + $this->name = $name; $this->price = $price; } - public function getName(): string { return $this->name; } - public function getPrice(): float { return $this->price; } + public function getName(): string { + return $this->name; + } + public function getPrice(): float { + return $this->price; + } } $json = new Json(); $product = new Product('Keyboard', 49.99); $json->addObject('product', $product); -echo $json . "\n"; +echo $json."\n"; // {"product":{"Name":"Keyboard","Price":49.99,"sku":"ABC-001"}} // ^ getters produce "Name"/"Price", public property adds "sku" diff --git a/examples/05-naming-styles.php b/examples/05-naming-styles.php index 0598724..4563217 100644 --- a/examples/05-naming-styles.php +++ b/examples/05-naming-styles.php @@ -1,16 +1,17 @@ 'Ibrahim', 'last-name' => 'Al-Shikh']; -echo new Json($data, 'none') . "\n"; // {"first-name":"Ibrahim","last-name":"Al-Shikh"} -echo new Json($data, 'camel') . "\n"; // {"firstName":"Ibrahim","lastName":"Al-Shikh"} -echo new Json($data, 'snake') . "\n"; // {"first_name":"Ibrahim","last_name":"Al-Shikh"} -echo new Json($data, 'kebab') . "\n"; // {"first-name":"Ibrahim","last-name":"Al-Shikh"} +echo new Json($data, 'none')."\n"; // {"first-name":"Ibrahim","last-name":"Al-Shikh"} +echo new Json($data, 'camel')."\n"; // {"firstName":"Ibrahim","lastName":"Al-Shikh"} +echo new Json($data, 'snake')."\n"; // {"first_name":"Ibrahim","last_name":"Al-Shikh"} +echo new Json($data, 'kebab')."\n"; // {"first-name":"Ibrahim","last-name":"Al-Shikh"} // Change style after construction + apply upper case $json = new Json($data); $json->setPropsStyle('snake', 'upper'); -echo $json . "\n"; // {"FIRST_NAME":"Ibrahim","LAST_NAME":"Al-Shikh"} +echo $json."\n"; // {"FIRST_NAME":"Ibrahim","LAST_NAME":"Al-Shikh"} diff --git a/examples/06-decode-and-read.php b/examples/06-decode-and-read.php index 4bc736e..e4b7fc0 100644 --- a/examples/06-decode-and-read.php +++ b/examples/06-decode-and-read.php @@ -1,20 +1,21 @@ get('name') . "\n"; // Ibrahim -echo $json->get('age') . "\n"; // 30 +echo $json->get('name')."\n"; // Ibrahim +echo $json->get('age')."\n"; // 30 // Read from file try { - $json = Json::fromJsonFile(__DIR__ . '/sample.json'); - echo $json->get('product') . "\n"; // Keyboard - echo $json->get('price') . "\n"; // 49.99 - echo ($json->get('inStock') ? 'true' : 'false') . "\n"; // true + $json = Json::fromJsonFile(__DIR__.'/sample.json'); + echo $json->get('product')."\n"; // Keyboard + echo $json->get('price')."\n"; // 49.99 + echo ($json->get('inStock') ? 'true' : 'false')."\n"; // true } catch (JsonException $e) { - echo 'Error: ' . $e->getMessage() . "\n"; + echo 'Error: '.$e->getMessage()."\n"; } diff --git a/examples/07-jsonx.php b/examples/07-jsonx.php index de3f00a..33117be 100644 --- a/examples/07-jsonx.php +++ b/examples/07-jsonx.php @@ -1,12 +1,13 @@ 'Ibrahim', - 'age' => 30, + 'name' => 'Ibrahim', + 'age' => 30, 'isEmployed' => true, ]); -echo $json->toJSONxString() . "\n"; +echo $json->toJSONxString()."\n"; diff --git a/php_cs.php.dist b/php_cs.php.dist index ac0a570..0b4f088 100644 --- a/php_cs.php.dist +++ b/php_cs.php.dist @@ -11,7 +11,7 @@ return $config->setRules([ 'align_multiline_comment' => [ 'comment_type' => 'phpdocs_only' ], - 'array_indentation' => [], + 'array_indentation' => true, 'array_syntax' => [ 'syntax' => 'short' ], From 928aaff43f444becfef9506d7eb876dc02413c44 Mon Sep 17 00:00:00 2001 From: Ibrahim BinAlshikh Date: Wed, 4 Mar 2026 02:12:37 +0300 Subject: [PATCH 5/5] ci: Updated Workflows - Added PHP 8.5 - Use of Specific Version of Reusable Workflow --- .github/workflows/php81.yaml | 4 ++-- .github/workflows/php82.yaml | 4 ++-- .github/workflows/php83.yaml | 10 ++++------ .github/workflows/php84.yaml | 4 ++-- .github/workflows/php85.yaml | 30 ++++++++++++++++++++++++++++++ 5 files changed, 40 insertions(+), 12 deletions(-) create mode 100644 .github/workflows/php85.yaml diff --git a/.github/workflows/php81.yaml b/.github/workflows/php81.yaml index fead114..77e68ff 100644 --- a/.github/workflows/php81.yaml +++ b/.github/workflows/php81.yaml @@ -8,14 +8,14 @@ on: jobs: test: name: Run Tests - uses: WebFiori/workflows/.github/workflows/test-php.yaml@main + uses: WebFiori/workflows/.github/workflows/test-php.yaml@v1.2.1 with: php-version: '8.1' code-coverage: name: Coverage needs: test - uses: WebFiori/workflows/.github/workflows/coverage-codecov.yaml@main + uses: WebFiori/workflows/.github/workflows/coverage-codecov.yaml@v1.2.1 with: php-version: '8.1' coverage-file: 'php-8.1-coverage.xml' diff --git a/.github/workflows/php82.yaml b/.github/workflows/php82.yaml index 978033a..9e431d3 100644 --- a/.github/workflows/php82.yaml +++ b/.github/workflows/php82.yaml @@ -8,7 +8,7 @@ on: jobs: test: name: Run Tests - uses: WebFiori/workflows/.github/workflows/test-php.yaml@main + uses: WebFiori/workflows/.github/workflows/test-php.yaml@v1.2.1 with: php-version: '8.2' phpunit-config: "tests/phpunit10.xml" @@ -16,7 +16,7 @@ jobs: code-coverage: name: Coverage needs: test - uses: WebFiori/workflows/.github/workflows/coverage-codecov.yaml@main + uses: WebFiori/workflows/.github/workflows/coverage-codecov.yaml@v1.2.1 with: php-version: '8.2' coverage-file: 'php-8.2-coverage.xml' diff --git a/.github/workflows/php83.yaml b/.github/workflows/php83.yaml index 8ecb808..616f348 100644 --- a/.github/workflows/php83.yaml +++ b/.github/workflows/php83.yaml @@ -12,7 +12,7 @@ jobs: test: name: Run Tests - uses: WebFiori/workflows/.github/workflows/test-php.yaml@main + uses: WebFiori/workflows/.github/workflows/test-php.yaml@v1.2.1 with: php-version: '8.3' phpunit-config: 'tests/phpunit10.xml' @@ -21,7 +21,7 @@ jobs: code-coverage: name: Coverage needs: test - uses: WebFiori/workflows/.github/workflows/coverage-codecov.yaml@main + uses: WebFiori/workflows/.github/workflows/coverage-codecov.yaml@v1.2.1 with: php-version: '8.3' coverage-file: 'php-8.3-coverage.xml' @@ -31,15 +31,13 @@ jobs: code-quality: name: Code Quality needs: test - uses: WebFiori/workflows/.github/workflows/quality-sonarcloud.yaml@main - with: - coverage-file: 'php-8.3-coverage.xml' + uses: WebFiori/workflows/.github/workflows/quality-sonarcloud.yaml@v1.2.1 secrets: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} release-prod: name: Prepare Production Release Branch / Publish Release needs: [code-coverage, code-quality] - uses: WebFiori/workflows/.github/workflows/release-php.yaml@main + uses: WebFiori/workflows/.github/workflows/release-php.yaml@v1.2.1 with: branch: 'main' diff --git a/.github/workflows/php84.yaml b/.github/workflows/php84.yaml index 1ce3097..adcc94b 100644 --- a/.github/workflows/php84.yaml +++ b/.github/workflows/php84.yaml @@ -8,7 +8,7 @@ on: jobs: test: name: Run Tests - uses: WebFiori/workflows/.github/workflows/test-php.yaml@main + uses: WebFiori/workflows/.github/workflows/test-php.yaml@v1.2.1 with: php-version: '8.4' phpunit-config: "tests/phpunit10.xml" @@ -16,7 +16,7 @@ jobs: code-coverage: name: Coverage needs: test - uses: WebFiori/workflows/.github/workflows/coverage-codecov.yaml@main + uses: WebFiori/workflows/.github/workflows/coverage-codecov.yaml@v1.2.1 with: php-version: '8.4' coverage-file: 'php-8.4-coverage.xml' diff --git a/.github/workflows/php85.yaml b/.github/workflows/php85.yaml new file mode 100644 index 0000000..e66edfc --- /dev/null +++ b/.github/workflows/php85.yaml @@ -0,0 +1,30 @@ +name: PHP 8.5 + +on: + push: + branches: [ main ] + pull_request: + branches: [ main, dev ] +env: + OPERATING_SYS: ubuntu-latest + PHP_VERSION: 8.5 +jobs: + + test: + name: Run Tests + uses: WebFiori/workflows/.github/workflows/test-php.yaml@v1.2.1 + with: + php-version: '8.5' + phpunit-config: 'tests/phpunit10.xml' + + + code-coverage: + name: Coverage + needs: test + uses: WebFiori/workflows/.github/workflows/coverage-codecov.yaml@v1.2.1 + with: + php-version: '8.5' + coverage-file: 'php-8.5-coverage.xml' + secrets: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} +