Skip to content

Commit

Permalink
Merge pull request #33 from Hi-Folks/feat/32-operator-like
Browse files Browse the repository at this point in the history
Operator Like
  • Loading branch information
roberto-butti authored Oct 12, 2024
2 parents 7ee26d7 + 6e09568 commit 7821ad0
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 12 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## 0.4.2 - WIP
- Implementing `getString()` for returning a string
- Implementing Operator Class with constans like Operator::EQUAL, Operator::GREATER_THAN ...
- Implementing LIKE Operator

## 0.4.1 - 2024-10-11
- Implementing `getFormattedByte()` for getting value as formatted byte
Expand Down
40 changes: 29 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ Retrieving JSON API into a Block object is useful for applying the methods provi
```php
$url = "https://api.github.com/repos/hi-folks/data-block/commits";
$commits = Block::fromJsonUrl($url);
$myCommits = $commits->where("commit.author.name", "like", "Roberto");
$myCommits = $commits->where("commit.author.name", Operator::LIKE, "Roberto");
foreach ($myCommits as $value) {
echo $value->get("commit.message") . PHP_EOL;
}
Expand Down Expand Up @@ -453,7 +453,7 @@ You can also set the operator
$composerContent = Block::fromJsonString($jsonString);
$banners = $composerContent->getBlock("story.content.body")->where(
"component",
"==",
Operator::EQUAL,
"banner",
);
```
Expand All @@ -465,7 +465,7 @@ If you want to avoid preserving the keys and set new integer keys starting from
$composerContent = Block::fromJsonString($jsonString);
$banners = $composerContent->getBlock("story.content.body")->where(
"component",
"!=",
Operator::NOT_EQUAL,
"banner",
+ false
);
Expand All @@ -477,19 +477,37 @@ With `where()` method you can use different operators, like "==", ">", "<" etc.

You can use also the `has` operator in the case your nested data contains arrays or `in` operator in the case you want to check if your data field value is included in an array of elements.

#### The operators

The `Operator` class provides a set of predefined constants that represent comparison and logical operators. This ensures type safety and prevents errors from using invalid or misspelled operators in your data comparisons.

Supported Operators:
- `Operator::EQUAL` (==)
- `Operator::GREATER_THAN` (>)
- `Operator::LESS_THAN` (<)
- `Operator::GREATER_THAN_OR_EQUAL` (>=)
- `Operator::LESS_THAN_OR_EQUAL` (<=)
- `Operator::NOT_EQUAL` (!=)
- `Operator::STRICT_NOT_EQUAL` (!==)
- `Operator::IN` (array inclusion)
- `Operator::HAS` (array containment)
- `Operator::LIKE` (string contains)

> The `Operator` class is defined in the `use HiFolks\DataType\Enums\Operator` namespace.
#### The `in` operator

The `in` operator is used within the where method to filter elements from a data collection based on whether a specific field's value exists within a given array of values.
The behavior is as follows:

```php
$data->where("field", "in", ["value1", "value2", ...])
$data->where("field", Operator::IN, ["value1", "value2", ...])
```

If the field's value exists in the provided array, the element is included in the result.
Example: Filtering fruits by color that match either "green" or "black"
```php
$greenOrBlack = $data->where("color", "in", ["green", "black"]);
$greenOrBlack = $data->where("color", Operator::IN, ["green", "black"]);
```

You should use the `in` operator if your field is a scalar type (for example string or number) and you need to check if it is included in a list of values (array).
Expand All @@ -499,7 +517,7 @@ You should use the `in` operator if your field is a scalar type (for example str
The `has` operator is used within the where method to filter elements from a data collection based on whether a specific field contains a given value, typically in cases where the field holds an array or a collection of tags or attributes. The behavior is as follows:

```php
$data->where("field", "has", "value")
$data->where("field", Operator::HAS, "value")
```

For example if you have posts and each post can have multiple tags, you can filter posts with a specific tag:
Expand All @@ -510,7 +528,7 @@ $posts = Block
::fromJsonUrl($url)
->getBlock("posts");

$lovePosts = $posts->where("tags", "has", "love");
$lovePosts = $posts->where("tags", Operator::HAS, "love");
```
#### Summary `in` VS `has`

Expand Down Expand Up @@ -570,7 +588,7 @@ If you want to retrieve elements with `product` and `price` keys, with a price g
$table = Block::make($dataTable);
$data = $table
->select('product' , 'price')
->where('price', ">", 100)
->where('price', Operator::GREATER_THAN, 100)
->orderBy("price");
print_r($data->toArray());
/*
Expand Down Expand Up @@ -670,7 +688,7 @@ You can apply filters and then loop into the result:
$table = Block::make($dataTable);
$data = $table
->select('product', 'price')
->where('price', ">", 100, false);
->where('price', Operator::GREATER_THAN, 100, false);
foreach ($data as $key => $item) {
echo $item->get("price"); // returns an integer
}
Expand All @@ -682,7 +700,7 @@ If you want to loop through `$data` and obtain the current `$item` variable as a

```php
$table = Block::make($dataTable, false);
$data = $table->select('product', 'price')->where('price', ">", 100, false);
$data = $table->select('product', 'price')->where('price', Operator::GREATER_THAN, 100, false);
foreach ($data as $key => $item) {
print_r($item); // $item is an array
}
Expand Down Expand Up @@ -721,7 +739,7 @@ $posts = Block::fromJsonUrl($url) // Load the Block from the remote URL
->getBlock("posts") // get the `posts` as Block object
->where(
field:"tags",
operator: "in",
operator: Operator::HAS,
value: "love",
preseveKeys: false,
) // filter the posts, selecting only the posts with tags "love"
Expand Down
2 changes: 2 additions & 0 deletions src/Enums/Operator.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@ class Operator
public const STRICT_NOT_EQUAL = '!==';
public const IN = 'in';
public const HAS = 'has';
public const LIKE = 'like';

}
1 change: 1 addition & 0 deletions src/Traits/QueryableBlock.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public function where(
Operator::STRICT_NOT_EQUAL => $elementToCheck->get($field) !== $value,
Operator::IN => in_array($elementToCheck->get($field), $value),
Operator::HAS => in_array($value, $elementToCheck->get($field)),
Operator::LIKE => str_contains($elementToCheck->get($field), $value),
default => $elementToCheck->get($field) === $value,
};
if ($found) {
Expand Down
16 changes: 16 additions & 0 deletions tests/Unit/Traits/QueryableBlockTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,19 @@ function () use ($fruitsArray): void {
expect($softFruit)->tohaveCount(1);
},
);


test(
'query with operators',
function (): void {
$data1 = Block::fromJsonFile(__DIR__ . "/../../data/commits-json/commits-10-p1.json");
$data2 = Block::fromJsonFile(__DIR__ . "/../../data/commits-json/commits-10-p2.json");
$data3 = Block::fromJsonFile(__DIR__ . "/../../data/commits-json/commits-10-p3.json");
$data1->append($data2)->append($data3);
expect($data1)->toHaveCount(30);
expect($data2)->toHaveCount(10);
$block = $data1->where("commit.author.name", Operator::LIKE, "Roberto");
expect($block->count())->toEqual(29);

},
);
2 changes: 1 addition & 1 deletion tests/data/commits-json/commits-10-p1.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"node_id": "C_kwDOMJrRd9oAKDQ5Nzg1MmYxODZiMTQ1MjBmM2EwNTkxNTg1M2ViODk1YWNhOTFiNzQ",
"commit": {
"author": {
"name": "Roberto Butti",
"name": "Robert Butti",
"email": "[email protected]",
"date": "2024-06-28T22:08:26Z"
},
Expand Down

0 comments on commit 7821ad0

Please sign in to comment.