Bump version to 1.1.0 by jvmvik · Pull Request #6 · serpapi/serpapi-php · GitHub
Skip to content

Bump version to 1.1.0 - #6

Open
jvmvik wants to merge 10 commits into
feature/ruby-parityfrom
chore/bump-version-1.1.0
Open

jvmvik wants to merge 10 commits into
feature/ruby-parityfrom
chore/bump-version-1.1.0

Conversation

@jvmvik

@jvmvik jvmvik commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Bumps Client::VERSION from 1.0.0 to 1.1.0, plus the README change log.

Why a minor bump

New features since 1.0.0, all backwards compatible:

  • Connection reuse (persistent, close())
  • Default search parameters in the constructor, and the array-style constructor
  • Associative array decoding (assoc)
  • API key masking in debug output (__debugInfo(), inspect())
  • Markdown output (markdown(), search_archive($id, 'md'))

No removals and no signature breaks, so a minor bump under semver rather than a major one.

Side effect worth knowing

Client::VERSION also feeds the source query parameter, so requests will start reporting serpapi-php:1.1.0 instead of serpapi-php:1.0.0. That is the intent — it makes the new release distinguishable in usage statistics — but it does mean this PR changes what goes over the wire, not just a constant.

Verified: Client::SOURCE resolves to serpapi-php:1.1.0, PHPStan level 6 clean, 108 tests passing.

For the reviewer

Based on feature/ruby-parity (#3), not Init, since it is those features this bump is versioning. Merge order: #3, then #5 (Markdown), then this.

composer.json intentionally carries no version field — Packagist derives it from the git tag, and a hardcoded field would be a second source of truth to keep in sync. Tagging 1.1.0 after merge is what actually publishes the release.

Related: the repo has no CHANGELOG.md; the change log lives as a README section, which is what this PR updates. Splitting it into a real changelog file is worth doing separately.

🤖 Generated with Claude Code

jvmvik and others added 10 commits August 10, 2026 07:07
The client sent `source=php`, which made it impossible to tell PHP client
versions apart in SerpApi usage statistics. Report `serpapi-php:<version>`
instead, matching the `serpapi-ruby:<version>` convention.

Query string assembly moves into a private `query()` method so it can be
covered without issuing an HTTP request.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The constructor only accepted api_key, engine and timeout, so parameters
like location, hl, gl or no_cache had to be repeated on every search call.
The Ruby client takes a hash where any unrecognized key becomes a default
search parameter.

Add a fourth positional argument for default parameters, and accept a
configuration array as the first argument for parity with the Ruby client.
Per-call parameters still take precedence, and null values are dropped from
the query rather than sent empty. Expose the effective defaults via
get_params(), alongside a get_timeout() accessor.

The existing positional signature is unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
var_dump() on a client printed the api_key property in clear text, so a key
could end up in logs or a bug report. The Ruby client masks it in inspect.

Add __debugInfo() to mask the key for var_dump and debuggers, plus an
inspect() method for parity. Keys of 8 characters or fewer are replaced
entirely rather than partially revealed.

print_r() and var_export() read properties directly and cannot be hooked;
this is called out in the docblock.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Every request created and destroyed its own cURL handle, paying for DNS,
TCP and TLS setup each time. The Ruby client keeps a persistent socket and
reports roughly twice the throughput because of it.

Keep one cURL handle per client and reuse it, so curl holds the connection
open between requests. Measured against the locations endpoint, follow-up
requests drop from ~110ms to ~22ms.

Persistent mode is on by default, matching the Ruby client, and can be
turned off with `['persistent' => false]`. close() releases the connection
and the client reconnects on the next request; the destructor closes it
too, so existing code needs no change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Responses were always decoded to stdClass, with no way to get arrays. The
Ruby client exposes symbolize_names for the equivalent choice.

Add an `assoc` option, settable on the client or per call. Error and
search_id extraction now reads either shape through a small dig() helper,
so exceptions carry the same context in both modes.

The default stays stdClass to keep existing code working, which is why this
is opt-in rather than mirroring Ruby's default.

search() and account() lose their `object` return type declaration since
they can now return an array; the docblocks carry the union type instead.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The suite covered 20 engines against the Ruby client's 38. Add examples for
amazon, yelp, yandex, google_news, google_news_light, google_images,
google_images_light, google_light, google_light_search, google_finance,
google_flights, google_hotels, google_patents, google_product,
google_reverse_image, google_trends, google_videos,
google_immersive_product and google_ai_overview.

Two of these are written differently from their Ruby counterparts:

- google_flights and google_hotels compute check-in and departure dates
  relative to today. The Ruby specs hardcode 2025 dates that have since
  passed.
- google_ai_overview reads page_token from a live Google search instead of
  a hardcoded token, and skips when Google returns no overview. The Ruby
  spec pins an expired token.

ClientIntegrationTest duplicated GoogleSearchTest assertion for assertion,
so it is removed.

These require an API key to run and were not executed here; only the
key-free unit tests were.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The Ruby client ships a demo directory used as out-of-box testing; the PHP
client had no runnable examples outside the test suite.

Add four scripts and a `make demo` target:

  demo.php             basic search
  demo_suggest.php     autocomplete, showing client-level default parameters
  demo_async.php       non-blocking batch submission collected via the
                       Search Archive API
  demo_persistent.php  connection reuse benchmark, needs no API key

demo_persistent.php measures a 2.6x speedup locally, in line with the Ruby
client's reported figure.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
CI ran the test suite but nothing checked types, despite the codebase
already carrying full @PARAM and @return annotations. The Ruby client gates
its build on rubocop.

Add PHPStan at level 6 over src/ and demo/, wired into `make analyse`,
`composer run-script analyse` and the workflow. Analysis is skipped on the
7.2 and 7.3 matrix entries, which predate PHPStan 2.

It caught one real problem: demo_async.php read ->search_metadata off a
value that search() can also return as an array, which would have surfaced
as a fatal error rather than a clear message. The demo now validates the
response shape first.

Test files are left out. Level 6 wants a return type on every test method,
which is churn across 40 files for little benefit.

The cURL handle type is excluded, with a comment: it is a resource on PHP 7
and a CurlHandle on PHP 8, and PHPStan only ever sees one version.

No code style fixer is added; the codebase uses 2-space indentation, so
PSR-12 enforcement would rewrite every file.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The test suite, demos and README used API_KEY, while the Ruby client and
SerpApi's own documentation use SERPAPI_KEY. Anyone working across both
libraries had to keep two names for the same secret.

SERPAPI_KEY is now the documented name everywhere. The test helper still
falls back to API_KEY so existing local setups keep working, and the
workflow reads `secrets.SERPAPI_KEY || secrets.API_KEY` so CI does not break
before the repository secret is renamed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
New features since 1.0.0, all backwards compatible: connection reuse,
default search parameters in the constructor, associative array decoding,
API key masking in debug output and Markdown output. A minor bump under
semver.

Client::VERSION also feeds the `source` query parameter, so requests now
report `serpapi-php:1.1.0` and the new release is distinguishable in usage
statistics.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant