schmunk42/php-bcx-client
Composer 安装命令:
composer require schmunk42/php-bcx-client
包简介
Modern PHP client for Basecamp 2 (BCX) API
README 文档
README
A modern, type-safe PHP 8.4 client for the Basecamp 2 API with OAuth 2.0 and HTTP Basic authentication support.
Features
- ✅ PHP 8.4+ with strict typing
- ✅ Multiple authentication methods (OAuth 2.0 & HTTP Basic)
- ✅ All 12 Basecamp 2 resources implemented
- ✅ 100% test coverage (119 tests, 371 assertions)
- ✅ Symfony HttpClient integration
- ✅ PSR-3 logging support
- ✅ PHPStan level 8 compliant
- ✅ PSR-12 code style
- ✅ Docker development environment
Installation
composer require schmunk42/php-bcx-client
Quick Start
Option 1: HTTP Basic Authentication (Simplest)
Perfect for development, debugging, and personal scripts:
<?php use Schmunk42\BasecampApi\Authentication\BasicAuthentication; use Schmunk42\BasecampApi\Client\BasecampClient; // Your Basecamp credentials $accountId = '999999999'; // Your account ID $username = 'you@example.com'; // Your Basecamp email $password = 'your-password'; // Your Basecamp password // Create authenticated client $auth = new BasicAuthentication($username, $password); $client = new BasecampClient($accountId, $auth); // Get all projects $projects = $client->projects()->all(); // Get current user $me = $client->people()->me(); echo "Logged in as: {$me['name']}\n";
Option 2: OAuth 2.0 (Recommended for Production)
For applications with multiple users:
<?php use Schmunk42\BasecampApi\Authentication\OAuth2Authentication; use Schmunk42\BasecampApi\Client\BasecampClient; // OAuth 2.0 access token (obtained through OAuth flow) $accessToken = 'BAhbByIBsHsidmVyc2lvbiI6MSwidXNlcl9pZCI...'; $accountId = '999999999'; // Create authenticated client $auth = new OAuth2Authentication($accessToken); $client = new BasecampClient($accountId, $auth); // Use the API $projects = $client->projects()->all();
See docs/OAUTH.md for complete OAuth 2.0 setup guide.
Requirements
- PHP 8.4 or higher
- Symfony HttpClient 7.0+
Available Resources
All 12 Basecamp 2 resources are fully implemented:
| Resource | Description | Example |
|---|---|---|
| Projects | Manage projects | $client->projects()->all() |
| Todolists | Todo lists in projects | $client->todolists()->all($projectId) |
| Todos | Individual tasks | $client->todos()->complete($projectId, $todoId) |
| People | Users and access | $client->people()->me() |
| Messages | Message board posts | $client->messages()->create($projectId, $data) |
| Comments | Comments on resources | $client->comments()->create($projectId, 'Todo', $todoId, $data) |
| Documents | Project documents | $client->documents()->all($projectId) |
| Uploads | File attachments | $client->uploads()->create($fileContent, $mimeType) |
| Events | Activity feed | $client->events()->all() |
| Calendar Events | Scheduled events | $client->calendarEvents()->all() |
| Topics | Content navigation | $client->topics()->allInProject($projectId) |
| Groups | User groups/companies | $client->groups()->all() |
Usage Examples
Projects
// List all projects $projects = $client->projects()->all(); // Get archived projects $archived = $client->projects()->archived(); // Create a new project $project = $client->projects()->create([ 'name' => 'New Project', 'description' => 'Project description', ]); // Archive a project $client->projects()->delete(123456);
Todos & Todolists
// Get all todolists in a project $todolists = $client->todolists()->all($projectId); // Get todos in a todolist $todos = $client->todos()->all($projectId, $todolistId); // Get all todos across all todolists in a project $allTodos = $client->todos()->allInProject($projectId); // Filter todos by due date $upcomingTodos = $client->todos()->allInProject($projectId, '2025-01-01'); // Get completed/remaining/trashed todos $completed = $client->todos()->getCompleted($projectId, $todolistId); $remaining = $client->todos()->getRemaining($projectId, $todolistId); $trashed = $client->todos()->getTrashed($projectId, $todolistId); // Project-level queries $allCompleted = $client->todos()->getAllCompletedInProject($projectId); $allRemaining = $client->todos()->getAllRemainingInProject($projectId); // Create a new todo $todo = $client->todos()->create($projectId, $todolistId, [ 'content' => 'Task description', 'due_at' => '2025-12-31', ]); // Mark todo as complete $client->todos()->complete($projectId, $todoId); // Global todolist queries $activeLists = $client->todolists()->allGlobal(); $completedLists = $client->todolists()->getCompletedGlobal(); $trashedLists = $client->todolists()->getTrashedGlobal(); // Get todolist with many items (1000+) - excludes todos for performance $largeTodolist = $client->todolists()->get($projectId, $todolistId, true);
People & User Management
// Get current user $me = $client->people()->me(); // Get all people $people = $client->people()->all(); // Get specific person $person = $client->people()->get($personId); // Get person's assigned todos across all projects $assignedTodos = $client->people()->getAssignedTodos($personId); // Filter assigned todos by due date $upcomingTasks = $client->people()->getAssignedTodos($personId, '2025-01-01'); // Get person's activity events $events = $client->people()->getEvents($personId); // Get all projects accessible to a person $projects = $client->people()->getProjects($personId); // Get trashed (deleted) users (admin only) $trashedUsers = $client->people()->getTrashed();
Messages & Comments
// Create a message $message = $client->messages()->create($projectId, [ 'subject' => 'Project Update', 'content' => 'Here is the latest update...', ]); // Add a comment to a message $comment = $client->comments()->create( $projectId, 'Message', $messageId, ['content' => 'Great update!'] );
File Uploads
// Upload a file (two-step process) $fileContent = file_get_contents('/path/to/file.pdf'); $upload = $client->uploads()->create($fileContent, 'application/pdf'); $token = $upload['token']; // Attach to a message $message = $client->messages()->create($projectId, [ 'subject' => 'Document attached', 'content' => 'See attached file', 'attachments' => [ ['token' => $token, 'name' => 'document.pdf'] ], ]);
Authentication
Finding Your Account ID
With Basic Auth:
$auth = new BasicAuthentication('you@example.com', 'password'); $client = new BasecampClient('999999999', $auth); // Try any number first $me = $client->people()->me(); // Will show your accounts
With OAuth 2.0:
curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
https://launchpad.37signals.com/authorization.json
The id field in the response is your Account ID.
OAuth 2.0 Setup
For production applications with multiple users, use OAuth 2.0:
- Register your app: https://launchpad.37signals.com/integrations
- Get access token: Follow the OAuth 2.0 flow
- Use with client: See docs/OAUTH.md for complete guide
Development
With Docker (Recommended)
# Clone repository git clone https://github.com/schmunk42/php-bcx-client.git cd php-bcx-client # Setup environment cp .env.example .env # Edit .env with your credentials # Install and test make install make test make phpstan make cs-check # Run examples make example # Basic usage make oauth-flow # OAuth 2.0 flow
Without Docker
composer install
composer test
composer phpstan
composer cs-check
Testing
# Run all tests make test # or composer test # Run with coverage docker compose run --rm php vendor/bin/phpunit --coverage-html coverage # Static analysis make phpstan # Code style make cs-fix
Error Handling
use Schmunk42\BasecampApi\Exception\AuthenticationException; use Schmunk42\BasecampApi\Exception\RequestException; try { $projects = $client->projects()->all(); } catch (AuthenticationException $e) { // Handle authentication errors (401) echo "Auth failed: " . $e->getMessage(); } catch (RequestException $e) { // Handle other API errors (400, 404, 500, etc.) echo "API error: " . $e->getStatusCode(); echo "Response: " . $e->getResponseBody(); }
Logging
Inject a PSR-3 logger for debugging:
use Monolog\Logger; use Monolog\Handler\StreamHandler; $logger = new Logger('basecamp'); $logger->pushHandler(new StreamHandler('php://stdout', Logger::DEBUG)); $client = new BasecampClient($accountId, $auth, null, $logger); // All API requests will be logged $projects = $client->projects()->all();
Documentation
- OAuth 2.0 Setup: docs/OAUTH.md - Complete guide with examples
- Code Examples: examples/ - Working examples for all features
- API Reference: https://github.com/basecamp/bcx-api - Official Basecamp 2 API docs
Contributing
Contributions are welcome! Please ensure:
- PHPUnit tests pass (
make test) - PHPStan level 8 passes (
make phpstan) - Code follows PSR-12 (
make cs-fix) - 100% test coverage for new code
License
MIT License. See LICENSE file.
Support
- Issues: https://github.com/schmunk42/php-bcx-client/issues
- API Docs: https://github.com/basecamp/bcx-api
Credits
- Built with Symfony HttpClient
- Inspired by the legacy netvlies/basecamp-php client
schmunk42/php-bcx-client 适用场景与选型建议
schmunk42/php-bcx-client 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 147 次下载、GitHub Stars 达 3, 最近一次更新时间为 2025 年 10 月 28 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「api」 「client」 「oauth」 「basecamp」 「bcx」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 schmunk42/php-bcx-client 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 schmunk42/php-bcx-client 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 schmunk42/php-bcx-client 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
WeChat OAuth SDK
Ory-Hydra OAuth 2.0 Client Provider for The PHP League OAuth2-Client
Library for ORCID web services
A lightweight and powerful OAuth 2.0 authorization and resource server library with support for all the core specification grants. This library will allow you to secure your API with OAuth and allow your applications users to approve apps that want to access their data from your API.
A PSR-7 compatible library for making CRUD API endpoints
Mock PSR-18 HTTP client
统计信息
- 总下载量: 147
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 3
- 点击次数: 16
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2025-10-28