Contracts Reference
This package is contract-first. Implementations (adapters) and higher-level features (graphs) speak the same language.
Query
Represents a provider-agnostic search/filter request with sensible defaults and validation.
Key fields
q: ?stringfull-text searchyear: ?stringYYYY or ranges like2018-or2019-2021openAccess: ?boolminCitations: ?int,maxCitations: ?intvenueIds: ?list<string>provider-specific venue identifiersfields: list<string>normalized selection of fields, case-insensitivelimit: intpage size (default 25)cursor: ?string,offset: ?intpagination controlsraw: array<string, mixed>for anything provider-specific
Construction
use Scholarly\Contracts\Query;
$q = Query::from([
'q' => 'deep learning',
'year' => '2018-2022',
'openAccess' => true,
'limit' => 50,
'fields' => ['id','title','year','authors'],
]);
// Or fluent
$q = (new Query())
->q('deep learning')
->year('2018-')
->openAccess(true)
->limit(50)
->addField('id')->addField('title');
Serialization
$asArray = $q->toArray();
Validation
- Empty
year→ InvalidArgumentException minCitations/maxCitationsmust be ≥ 0limit≥ 1,offset≥ 0
Paginator
Lazy, typed pagination for provider responses.
API
page(): array{items: list<array<string,mixed>>, nextCursor: ?string}getIterator(): Traversable<int, array<string, mixed>>
Usage
$paginator = $adapter->searchWorks($q);
// Pull a page
[$items, $cursor] = [$paginator->page()['items'], $paginator->page()['nextCursor']];
// Or stream lazily
foreach ($paginator as $row) {
// $row is normalized
}
ScholarlyDataSource
Unified interface across all adapters. Work and author endpoints mirror common capabilities.
Works
searchWorks(Query): PaginatorgetWorkById(string): ?arraygetWorkByDoi(string): ?arraygetWorkByArxiv(string): ?arraygetWorkByPubmed(string): ?arraylistCitations(string, Query): PaginatorlistReferences(string, Query): PaginatorbatchWorksByIds(iterable<string>, Query): iterable<array>
Authors
searchAuthors(Query): PaginatorgetAuthorById(string): ?arraygetAuthorByOrcid(string): ?arraybatchAuthorsByIds(iterable<string>, Query): iterable<array>
Meta
health(): boolshould handle transient errors internallyrateLimitState(): array{string:int|null}
Normalized shapes (typical)
- Work:
['id','title','year','venue','authors','counts'=>['citations'=>int], 'external_ids'=>['doi'=>?, 'arxiv'=>?, 'pmid'=>?]] - Author:
['id','name','orcid'=>?, 'affiliations'=>list<string>, 'counts'=>['works'=>int,'citations'=>int]]
Exceptions
- Adapters throw specialized exceptions under
Scholarly\Core\Exceptions(e.g.,NotFoundException,RateLimitException,ClientException).
Related Documentation
| Core Concepts: Contracts | Architecture | Getting Started |
| Features: Graph Analytics | Laravel Integration | Provider Adapters |
| Development: Extending | GitHub Repository |
| External Resources: OpenAlex API | Semantic Scholar API | Crossref API |