PHPackages                             globyapp/odata-query-parser - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. globyapp/odata-query-parser

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

globyapp/odata-query-parser
===========================

Parse OData v4 query strings, outputs proper PHP objects.

v1.2.0(10mo ago)12.4k↑200%[4 issues](https://github.com/Globy-App/odata-query-parser/issues)MITPHPPHP &gt;=8.2CI passing

Since Apr 23Pushed 3mo agoCompare

[ Source](https://github.com/Globy-App/odata-query-parser)[ Packagist](https://packagist.org/packages/globyapp/odata-query-parser)[ RSS](/packages/globyapp-odata-query-parser/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (7)Dependencies (6)Versions (11)Used By (0)

Odata Query Parser
==================

[](#odata-query-parser)

Parse OData v4 query strings, outputs proper PHP objects.

[![Packagist Version](https://camo.githubusercontent.com/ca4e645d5187992d87d5e4f081d4783c644a4308fd800476571d74ccc772c14b/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f676c6f62796170702f6f646174612d71756572792d706172736572)](https://packagist.org/packages/globyapp/odata-query-parser) [![Packagist](https://camo.githubusercontent.com/52ebcfa6aa3655d677745a4ab477eaf8ad349a698b34b3855e9591df95ec4712/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f676c6f62796170702f6f646174612d71756572792d706172736572)](https://github.com/Globy-App/odata-query-parser/blob/master/LICENSE) [![PHP from Packagist](https://camo.githubusercontent.com/18b375cce1fd7e7a72b6c3ca4fa0e25b4dcb170986147e759461e6212eb51e0b/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f676c6f62796170702f6f646174612d71756572792d706172736572)](https://github.com/globyapp/odata-query-parser/blob/master/composer.json#L14) [![CI](https://github.com/Globy-App/odata-query-parser/actions/workflows/ci.yml/badge.svg)](https://github.com/Globy-App/odata-query-parser/actions/workflows/ci.yml)

Summary
-------

[](#summary)

- [About](#about)
- [Features](#features)
- [Requirements](#requirements)
- [Installation](#installation)
- [Examples](#examples)
- [API](#api)
- [Known issues](#known-issues)
- [Thanks](#thanks)

About
-----

[](#about)

I needed to only parse query strings to convert OData v4 commands into an understandable array that I could use to make a Laravel package to offer a way to automatically use Eloquent to filter the response according to this parsed array of OData v4 command.

As I did not see a package exclusively dealing with parsing the query strings, and saw that [some people worked on their own without open sourcing it](https://stackoverflow.com/questions/14145604/parse-odata-query-uri-into-php-array), I decided I would start one myself.

Features
--------

[](#features)

- Parses an URL and returns an array
- Supports `$select`, `$top`, `$skip`, `$orderby`, `$count`
- Partial support for `$filter` (see [Known issues](#known-issues) section)
- You can use a parse mode that let you parse these keywords without prepending `$`

Requirements
------------

[](#requirements)

- PHP &gt;= 8.2.0
- [Composer](https://getcomposer.org/)

Installation
------------

[](#installation)

Add the package to your dependencies:

```
composer require globyapp/odata-query-parser
```

Examples
--------

[](#examples)

### 1. Use $select to filter on some fields

[](#1-use-select-to-filter-on-some-fields)

In this example, we will use the `$select` OData query string command to filter the fields returned by our API.

```
use GlobyApp\OdataQueryParser\OdataQueryParser;

$data = OdataQueryParser::parse('https://example.com/api/user?$select=id,name,age');
```

If you inspect `$data`, this is what you will get:

```
object(GlobyApp\OdataQueryParser\OdataQuery)#2 (6) {
  ["select":"GlobyApp\OdataQueryParser\OdataQuery":private]=>
  array(3) {
    [0]=>
    string(2) "id"
    [1]=>
    string(4) "name"
    [2]=>
    string(3) "age"
  }
  ...
}
```

### 2. Use non dollar syntax

[](#2-use-non-dollar-syntax)

In this example, we will use a unique feature of this library: to be able to not specify any dollar, while still being able to use the OData v4 URL query parameter grammar.

```
use GlobyApp\OdataQueryParser\OdataQueryParser;

$data = OdataQueryParser::parse("https://example.com/api/user?select=id,name,age", $withDollar = false);
```

If you inspect `$data`, this is what you will get:

```
object(GlobyApp\OdataQueryParser\OdataQuery)#2 (6) {
  ["select":"GlobyApp\OdataQueryParser\OdataQuery":private]=>
  array(3) {
    [0]=>
    string(2) "id"
    [1]=>
    string(4) "name"
    [2]=>
    string(3) "age"
  }
  ...
}
```

API
---

[](#api)

```
OdataQueryParser::parse(string $url, bool $withDollar = true): OdataQuery;
```

### Parameters

[](#parameters)

- string `$url`: The URL to parse the query strings from. It should be a "complete" or "full" URL, which means that `https://example.com` will pass while `example.com` will not pass
- bool `$withDollar`: Set it to false if you want to parse query strings without having to add the `$` signs before each key.

### Returns

[](#returns)

An OdataQuery object:

```
return = OdataQuery {
	select => array,
	count => bool|null,
	top => int|null,
	skip => int|null,
	orderBy => array,
	filter => array
};

OrderByClause {
	property => string,
	direction => OrderDirection
}

OrderDirection = "ASC" | "DESC"

FilterClause {
	property => string,
	operator => string,
	value => int|float|string|bool|null|array
}
```

### Throws

[](#throws)

- `InvalidArgumentException`
    - If the parameter `$url` is not a valid URL (see the parameter description to know what is a valid URL)
    - If the `$top` query string value is not an integer
    - If the `$top` query string value is lower than 0
    - If the `$skip` query string value is not an integer
    - If the `$skip` query string value is lower than 0
    - If the `$count` query string value is not a boolean
    - If the formatting of `$orderby` is not valid (should be a property, space and the direction)
    - If the direction of the `$orderby` query string value is neither `asc` or `desc` (case-insensitive)
        - This will throw an InvalidDirectionException, inheriting InvalidArgumentException.
    - If the formatting of `$filter` is not valid (should be a property, space, operator, space and value)
    - If the operator of the `$filter` query string value is not `eq`, `ne`, `gt`, `ge`, `lt`, `le` or `in` (case-insensitive)
        - This will throw an InvalidFilterOperatorException, inheriting InvalidArgumentException.
- `LogicException`
    - If an unforeseen edge case is triggered by an input value. For example when a regex operation fails. Should never be thrown under normal operation.
        - If an edge case is found, please report them as an issue. Currently, I cannot write test cases for them as I don't know how to trigger them.

Known issues
------------

[](#known-issues)

- `$filter` command will not parse `or` and functions (like `contains()` of `substringof`), because I did not focus on this for the moment (the parser for `$filter` is too simplistic, I should find a way to create an AST).

Thanks
------

[](#thanks)

Feel free to open any issues or PRs.

---

MIT © 2024

###  Health Score

38

—

LowBetter than 85% of packages

Maintenance48

Moderate activity, may be stable

Popularity23

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity60

Established project with proven stability

 Bus Factor1

Top contributor holds 84.7% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~71 days

Recently: every ~104 days

Total

7

Last Release

327d ago

Major Versions

v0.3.0 → v1.0.02024-05-06

PHP version history (2 changes)v0.2.0PHP &gt;=8.1.0

v0.3.0PHP &gt;=8.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/df138e9cc459c67079fc4e09b80363fb03d22aabcd524e86282cb714995fab97?d=identicon)[GlobyApp](/maintainers/GlobyApp)

---

Top Contributors

[![Sjustein](https://avatars.githubusercontent.com/u/30069718?v=4)](https://github.com/Sjustein "Sjustein (50 commits)")[![khalyomede](https://avatars.githubusercontent.com/u/15908747?v=4)](https://github.com/khalyomede "khalyomede (9 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan, Psalm

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/globyapp-odata-query-parser/health.svg)

```
[![Health](https://phpackages.com/badges/globyapp-odata-query-parser/health.svg)](https://phpackages.com/packages/globyapp-odata-query-parser)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
