定制 codebes/gripp-sdk 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

codebes/gripp-sdk

Composer 安装命令:

composer require codebes/gripp-sdk

包简介

PHP SDK for the Gripp CRM/ERP API. Fluent query builder, batch operations, and 54 resources for project management, invoicing, time tracking, and more.

README 文档

README

Latest Version on Packagist Tests PHPStan License: MIT PHP Version

A PHP SDK for the Gripp (now Exact Gripp) CRM/ERP API. Manage companies, contacts, projects, invoices, time tracking, and 50+ other resources through a fluent query builder with batch operations, auto-pagination, and automatic retries. Works with any PHP 8.1+ application, including Laravel.

Features

  • Fluent query builder with 14 filter operators
  • Full CRUD support on 54 Gripp resources
  • Batch operations (multiple API calls in a single HTTP request)
  • Auto-pagination for large datasets
  • Automatic retries on server errors and connection failures
  • Typed exceptions for authentication, rate limiting, and API errors
  • Laravel Collection responses out of the box
  • Self-documenting resources with field types, required fields, and relationship metadata

Requirements

  • PHP 8.1+
  • A Gripp API token and API URL

Installation

composer require codebes/gripp-sdk

Configuration

Option 1: Environment variables

Set GRIPP_API_TOKEN in your .env file or environment:

GRIPP_API_TOKEN=your-api-token

Then call configure without arguments:

use CodeBes\GrippSdk\GrippClient;

GrippClient::configure();

The SDK uses https://api.gripp.com by default. To override, set GRIPP_API_URL in your environment.

Option 2: Explicit configuration

use CodeBes\GrippSdk\GrippClient;

GrippClient::configure(token: 'your-api-token');

Option 3: Interactive setup

vendor/bin/gripp-setup

This creates a .env file with your credentials.

Quick Start

use CodeBes\GrippSdk\GrippClient;
use CodeBes\GrippSdk\Resources\Company;
use CodeBes\GrippSdk\Resources\Contact;
use CodeBes\GrippSdk\Resources\Project;

// Configure once at application boot
GrippClient::configure();

// Find a record by ID
$company = Company::find(123);

// Get all records (auto-paginated)
$allCompanies = Company::all();

// Query with filters
$activeCompanies = Company::where('active', true)
    ->orderBy('companyname', 'asc')
    ->limit(50)
    ->get();

// Create a record
$result = Company::create([
    'companyname' => 'Acme Corp',
    'relationtype' => 'COMPANY',
    'email' => 'info@acme.com',
]);

// Update a record
Company::update(123, [
    'phone' => '+31 20 123 4567',
]);

// Delete a record
Company::delete(123);

Query Builder

The query builder provides a fluent interface for filtering, ordering, and paginating results.

use CodeBes\GrippSdk\Resources\Project;

// Simple equality filter (two-argument form)
$projects = Project::where('company', 42)->get();

// With operator (three-argument form)
$projects = Project::where('name', 'contains', 'Website')->get();

// Chain multiple filters
$results = Project::where('company', 42)
    ->where('archived', false)
    ->orderBy('createdon', 'desc')
    ->limit(25)
    ->offset(0)
    ->get();

// Get just the first match
$project = Project::where('name', 'contains', 'Redesign')->first();

// Count matching records
$count = Project::where('archived', false)->count();

Supported Filter Operators

Operator Description
equals Exact match (default when using two-argument where)
notequals Not equal to
contains String contains
notcontains String does not contain
startswith String starts with
endswith String ends with
greaterthan Greater than
lessthan Less than
greaterequals Greater than or equal to
lessequals Less than or equal to
in Value is in array
notin Value is not in array
isnull Field is null (pass true as value)
isnotnull Field is not null (pass true as value)

Date Helpers

Common date filtering patterns are built into the query builder:

use CodeBes\GrippSdk\Resources\Project;
use CodeBes\GrippSdk\Resources\Hour;

// Filter by year
$projects = Project::where('archived', false)
    ->whereYear('createdon', 2026)
    ->get();

// Filter by month
$hours = Hour::where('employee', 42)
    ->whereMonth('date', 2026, 3)
    ->get();

// Filter by date range
$invoices = Invoice::where('company', 10)
    ->whereDateBetween('date', '2026-01-01', '2026-03-31')
    ->get();

// Modified since (for incremental syncing)
$updated = Project::where('archived', false)
    ->whereModifiedSince(new DateTime('2026-03-01 00:00:00'))
    ->get();

Auto-Prefixing

Field names are automatically prefixed with the entity name when using the query builder. Writing Project::where('createdon', ...) produces the filter field project.createdon. Fully qualified fields like project.createdon are left as-is.

Auto-Pagination

Both get() and the query builder's get() automatically paginate through all results. Use limit() when you only want a specific number of results (single API call):

// Fetches ALL matching projects across all pages
$all = Project::where('archived', false)->get();

// Fetches only the first 25 (single page)
$page = Project::where('archived', false)->limit(25)->get();

Batch Operations

Group multiple API calls into a single HTTP request for better performance:

use CodeBes\GrippSdk\GrippClient;
use CodeBes\GrippSdk\Resources\Company;
use CodeBes\GrippSdk\Resources\Contact;

$transport = GrippClient::getTransport();
$transport->startBatch();

// Queue multiple calls (these don't execute yet)
Company::find(1);
Company::find(2);
Contact::find(10);

// Execute all queued calls in a single HTTP request
$responses = $transport->executeBatch();

foreach ($responses as $response) {
    $rows = $response->rows();
    // Process each response...
}

Rate Limit Awareness

The transport tracks rate limit headers from API responses and provides hooks for proactive budget management:

$transport = GrippClient::getTransport();

// Check current rate limit state (from most recent response headers)
$transport->getRateLimitRemaining(); // e.g. 847
$transport->getRateLimitLimit();     // e.g. 1000

// Abort requests when budget is low
$transport->beforeRequest(function (int $requestCount, ?int $remaining, ?int $limit) {
    if ($remaining !== null && $remaining <= 5) {
        throw new \RuntimeException("Only {$remaining} API calls left!");
    }
});

// React when a 429 or 503 rate limit hits
$transport->onRateLimitExceeded(function (?int $retryAfter, ?int $remaining) {
    // Set a flag, notify monitoring, etc.
    Log::warning("Gripp rate limit hit, retry after {$retryAfter}s");
});

The SDK treats both HTTP 429 and HTTP 503 with Gripp error code 1004 (short-burst throttle) as rate limit errors.

Error Handling

The SDK throws specific exceptions for different error types:

use CodeBes\GrippSdk\Exceptions\AuthenticationException;
use CodeBes\GrippSdk\Exceptions\RateLimitException;
use CodeBes\GrippSdk\Exceptions\RequestException;
use CodeBes\GrippSdk\Exceptions\GrippException;

try {
    $company = Company::find(123);
} catch (AuthenticationException $e) {
    // 401 or 403 - invalid token or forbidden
    if ($e->isTokenInvalid()) {
        // Handle invalid/expired token
    }
    if ($e->isForbidden()) {
        // Handle insufficient permissions
    }
} catch (RateLimitException $e) {
    // 429 - too many requests
    $retryAfter = $e->getRetryAfter(); // seconds to wait
    $remaining = $e->getRemaining();   // remaining requests
} catch (RequestException $e) {
    // Other API errors
    $data = $e->getResponseData(); // raw error response
} catch (GrippException $e) {
    // Base exception for all SDK errors (e.g. not configured)
}

Available Resources

All resources support read operations. Resources that also support create, update, and/or delete are indicated below.

Resource Create Read Update Delete
AbsenceRequest x x x x
AbsenceRequestLine x x x x
BulkPrice x x x x
CalendarItem x x x x
Company x x x x
CompanyDossier x x x x
Contact x x x x
Contract x x x x
ContractLine x x x x
Cost x
CostHeading x x x x
Department x x x x
Employee x x x x
EmployeeFamily x x x x
EmployeeTarget x
EmployeeYearlyLeaveBudget x x x
EmploymentContract x x x x
ExternalLink x x x x
File x
Hour x x x x
Invoice x x x x
InvoiceLine x x x x
Ledger x x x x
Memorial x
MemorialLine x
Notification
Offer x x x x
OfferPhase x x x x
OfferProjectLine x x x x
Packet x x x x
PacketLine x x x x
Payment x x x x
PriceException x x x x
Product x x x x
Project x x x x
ProjectPhase x x x x
PurchaseInvoice x x x x
PurchaseInvoiceLine x x x x
PurchaseOrder x x x x
PurchaseOrderLine x x x x
PurchasePayment x x x x
RejectionReason x x x x
RevenueTarget x
Tag x x x x
Task x x x x
TaskPhase x x x x
TaskType x x x x
TimelineEntry x x x x
UmbrellaProject x x x
Unit x x x x
Webhook x x x x
YearTarget x
YearTargetType x

Special resources:

  • Notification has custom emit() and emitall() methods instead of CRUD.
  • Company has additional getCompanyByCOC(), addInteractionByCompanyId(), and addInteractionByCompanyCOC() methods.

Resource Metadata

Every resource class exposes constants that describe its schema:

use CodeBes\GrippSdk\Resources\Company;

Company::FIELDS;    // ['id' => 'int', 'companyname' => 'string', ...]
Company::READONLY;  // ['createdon', 'updatedon', 'id', 'searchname', 'files']
Company::REQUIRED;  // ['relationtype']
Company::RELATIONS; // ['accountmanager' => Employee::class, 'tags' => Tag::class, ...]
  • FIELDS maps field names to their types (string, int, float, boolean, datetime, date, array, customfields, color)
  • READONLY lists fields that cannot be written to
  • REQUIRED lists fields that must be provided when creating/updating
  • RELATIONS maps foreign key fields to their related resource classes

Auto-Pagination

Both all() and get() automatically handle pagination, fetching all matching records transparently:

// Fetches all companies, regardless of how many pages it takes
$companies = Company::all(); // Returns Illuminate\Support\Collection

// Filtered queries also auto-paginate
$active = Company::where('active', true)->get(); // All pages

Response Format

All collection methods return Illuminate\Support\Collection instances. Single-record methods return associative arrays or null.

$companies = Company::where('active', true)->get();

// Use Collection methods
$names = $companies->pluck('companyname');
$grouped = $companies->groupBy('visitingaddress_city');
$first = $companies->first();

Testing

composer test

Or directly:

vendor/bin/phpunit

Changelog

Please see the GitHub Releases page for more information on what has changed recently.

Contributing

Contributions are welcome! Please open a pull request against the main branch. All PRs require:

  • Passing tests (composer test)
  • Code style compliance (composer cs)
  • Static analysis passing (composer analyse)
  • Code owner approval

License

MIT - see LICENSE for details.

codebes/gripp-sdk 适用场景与选型建议

codebes/gripp-sdk 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 62 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 02 月 27 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「php」 「api」 「Guzzle」 「sdk」 「crm」 「laravel」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 codebes/gripp-sdk 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 codebes/gripp-sdk 我们能提供哪些服务?
定制开发 / 二次开发

基于 codebes/gripp-sdk 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 62
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 34
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-02-27