Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Box Laravel Package

dcblogdev/laravel-box

Laravel Box provides a simple integration with the Box API, letting Laravel apps authenticate and manage files and folders through Box. It wraps Box SDK configuration and offers convenient access from your Laravel project.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Install and publish: composer require dcblogdev/laravel-box, then publish the config (and migrations, if the package ships a token table) with php artisan vendor:publish --provider="Dcblogdev\Box\BoxServiceProvider". This package is one of the dcblogdev family (Dropbox/OneDrive/Box), so the shape is familiar: a service provider, a config/box.php, an OAuth connect/callback route pair, and a Box facade.
  • Where to look first: the published config/box.php (client ID, client secret, redirect URI, and the token storage driver), then vendor/dcblogdev/laravel-box/src/ to see the actual client classes and route names. The README gives you the OAuth dance; the source gives you the method surface, which is rarely fully documented.
  • Credentials: create a Box application in the Box Developer Console, set the OAuth 2.0 redirect URI to exactly what your config says (typically https://your-app.test/box/oauth/callback), and select the right app type — box's "Standard OAuth 2.0 (User Authentication)" vs "JWT" decision is made in the console, and only OAuth 2.0 user auth fits this package's flow.
  • First use case: an authenticated read. Hit the connect route as a logged-in user, complete consent, confirm a token row/record was persisted, then call the facade from php artisan tinker, e.g. Box::files()->listContents('0') or Box::folders()->all(), to prove end-to-end wiring before building anything real.
  • Upgrading to v2.1.9: this release is a composer.json constraint widening for Laravel 13 only — no code changes, no API changes. If you're pinned to ^2.1.8 on Laravel 12, nothing moves until you bump Laravel. If you're moving to Laravel 13, pull ^2.1.9 in the same commit as the framework upgrade and confirm your PHP version satisfies Laravel 13's floor.

Implementation Patterns

  • Wrap the facade, don't sprinkle it. Put Box behind a small BoxStorage / CloudStorage service (or an interface with a fake implementation) so your domain code never imports the vendor facade. This is what makes the package testable and swappable later.
  • Abstract the vendor behind an interface if Box is one of several providers. dcblogdev's packages (Dropbox, OneDrive, Box, Google Drive) expose similar-but-not-identical surfaces; a thin upload(string $path, $contents): string and download(string $id): string contract keeps your callers provider-agnostic.
  • Token lifecycle: treat the stored token as the source of truth, not the session. Refresh proactively (Box access tokens are short-lived — roughly an hour) by calling the package's refresh path from a scheduled job or a middleware, so user requests don't pay the refresh round-trip. Add a Box::refreshToken()-style call to a php artisan box:refresh command scheduled every ~45 minutes for single-tenant apps.
  • Background work is the normal case. Queued jobs and console commands have no OAuth session, so anything asynchronous must load tokens from persistence. Design the app so the "connected account" concept is data (a row keyed to your user/tenant), not a browser cookie.
  • Folder-as-tenant convention. Use Box folders (Box::folders()->create(...)) as the tenant boundary — create one folder per customer/project on onboarding, store the Box folder ID on your model, and never resolve folders by name at runtime (names are not unique and are user-renamable).
  • Webhooks over polling. If you need change notifications, register a Box webhook pointing at a route you control and verify the signature; the package's request builder is not a webhook verifier. Don't poll listContents in a loop — you'll hit rate limits fast.
  • Large uploads: Box's simple upload is capped (50 MB); beyond that you need the chunked/session upload flow. Check whether the package version you're on exposes it, and if not, drop to a direct Guzzle call using the same access token rather than fighting the wrapper.
  • Testing: Laravel's Http::fake() only intercepts the default Laravel HTTP client. If the package builds its own Guzzle client, fake at your own boundary (swap your BoxStorage implementation) or use a Guzzle MockHandler bound into the container.

Gotchas and Tips

  • Redirect URI must match byte-for-byte, including trailing slash and http vs https. A mismatch surfaces as a generic Box invalid_request on the callback, which looks like a code bug but is a config bug. Check APP_URL and any proxy/TrustProxies setup that rewrites the scheme.
  • Config caching bites OAuth. After changing credentials in .env, run php artisan config:clear; a cached config will keep sending the old client secret and Box will return invalid_client with no useful detail.
  • Errors arrive as JSON, not exceptions you'd expect. Box returns {"type":"error","status":4xx,"code":"...","context_info":{...}}. The package may surface a raw response or a generic exception — log the full body, because item_name_invalid vs item_name_too_long vs conflict all look alike otherwise.
  • 429 handling is on you. Box rate-limits per-user and returns Retry-After; naive retry loops make it worse. Add jittered backoff and, for bulk operations, throttle with Bus::batch()->allowFailures() plus a rate limiter.
  • 403 vs 401 are different problems. 401 means the token is stale — refresh. 403 usually means the authenticated Box user lacks access to the folder/file ID, or the app's Console configuration doesn't grant the required scope. Don't refresh-loop on 403.
  • IDs are strings and can be surprising. Box folder ID 0 is root; don't treat 0 as falsy in your code (if (!$folderId) silently redirects everything to root). Cast to string and compare explicitly.
  • Token storage is the extension point. If the default single-row token table doesn't fit multi-tenant, bind your own token repository in a service provider rather than editing vendor code — the package is small and its persistence is usually the easiest thing to swap.
  • Pinning: since v2.1.9 only widens the framework constraint, pinning ^2.1 is safe and gets you Laravel 13 compatibility for free when you get there. If you're stuck on Laravel 12 for a while, there is no reason to hold back on this release.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib