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

Mindbodyonline Api Bundle Laravel Package

wmds/mindbodyonline-api-bundle

Symfony bundle that integrates the Mindbody Online API into your PHP application, offering ready-made services and configuration for booking, scheduling, and client data access. Simplifies authentication and API calls so you can connect to Mindbody faster.

View on GitHub
Deep Wiki
Context7

Getting Started

This bundle is a thin Symfony 2 wrapper around the MindBody SOAP API (Class, Client, Appointment, Sale, Staff, Site services). It predates Symfony Flex, autowiring, and the MindBody REST API, so treat it as glue code you will likely extend rather than a batteries-included integration.

  1. Install and register

    composer require wmds/mindbodyonline-api-bundle
    
    // app/AppKernel.php
    public function registerBundles()
    {
        $bundles = [
            // ...
            new WMDS\MindBodyAPIBundle\WMDSMindBodyAPIBundle(),
        ];
    }
    
  2. Configure credentials in app/config/config.yml (verify exact keys against DependencyInjection/Configuration.php before committing to them):

    wmds_mind_body_api:
        api_key:        %mindbody_api_key%
        site_id:        %mindbody_site_id%
        source_name:    %mindbody_source_name%
        source_password: %mindbody_source_password%
    

    Keep the values in parameters.yml / environment-specific config. MindBody has two credential pairs — the API key (developer/source) and site credentials (staff user/password for a studio) — and mixing them up is the most common first-day failure.

  3. Find the service ID. Open Resources/config/services.xml (and DependencyInjection/) first. The bundle exposes either a single facade (commonly mindbody.api or similar) or one service per MindBody service. Also read the README and any Tests/ fixtures; with 4 stars there is minimal documentation, so the service definition is the source of truth.

  4. First useful call — pull a week of classes and confirm the round-trip works before wiring anything into your domain:

    $api = $this->get('mindbody.api'); // check services.xml for the real id
    
    $classes = $api->getClasses([
        'StartDateTime' => new \DateTime('today'),
        'EndDateTime'   => new \DateTime('+7 days'),
        'PageSize'      => 100,
    ]);
    

If you are on a modern Symfony, plan to install this only as a reference: copy the request/response plumbing into a small client of your own (Guzzle/SOAP + DTOs) rather than fighting Symfony 2 bundle conventions.

Implementation Patterns

Wrap the bundle in your own service. Never let controllers call the MindBody service directly. Create AppBundle\MindBody\MindBodyGateway that injects the bundle service, owns pagination, retries, and mapping. This isolates the (likely abandoned) dependency behind an interface you can swap for the REST API later.

Separate read models from write operations. For day-to-day work the split is almost always:

  • Reads (schedule, staff, locations, client lookup): cache aggressively — classes and locations change slowly and MindBody rate-limits per source.
  • Writes (add client, book class, purchase contract, add appointment): validate locally first, then call, then persist a local record keyed by the MindBody ID so you can reconcile.

Booking flow pattern — the most common integration shape:

public function bookClass($clientId, $classId)
{
    $client = $this->gateway->getClient($clientId);
    $class  = $this->gateway->getClass($classId, ['StaffCredentials' => ...]);

    if ($class->isCancelled() || $class->getSpotsOpen() < 1) {
        throw new BookingUnavailable('Class full or cancelled');
    }

    $result = $this->gateway->addClientToClass($clientId, $classId);

    $this->repository->recordBooking($clientId, $classId, $result->getId());
}

Always re-read availability immediately before booking; the schedule cache is for display only.

Sync via console commands. Nightly or hourly commands (app/console mindbody:sync-classes, mindbody:sync-clients) keep local tables warm. Use PageIndex/PageSize with an explicit ceiling and a while loop — MindBody defaults to small page sizes, and an unpaginated call silently returns only the first page.

DTO mapping layer. SOAP responses come back as nested stdClass/arrays with inconsistent casing (ClassScheduleID vs ClassScheduleId). Map once into typed objects in a single ResponseMapper; every other layer should be free of MindBody-shaped data. This is also where you normalise datetimes to the site's timezone and money to integer cents.

Testing. Because the bundle calls out over SOAP, mock your own gateway interface in tests. For an integration smoke test, only run against the MindBody sandbox credentials and mark it @group integration.

Event hooks for side effects. Dispatch your own domain events (ClientAddedEvent, ClassBookedEvent) after a successful MindBody call so email/Slack/ERP listeners stay decoupled from SOAP.

Gotchas and Tips

  • Symfony 2 is EOL. PHP 7.x/8.x compatibility is unlikely out of the box. If you're on Symfony 4+, this package will not autowire; expect to fork it, drop the bundle boilerplate, and keep only the API client.
  • SOAP extension required. You need ext-soap. WSDL caching can make schema changes look stale — disable soap.wsdl_cache in dev or clear the cache after deploy.
  • Credentials vs. site ID. The source credentials authenticate your application; the site ID and staff credentials select which studio's data you see. Many endpoints require both. A 401/AccessDenied is more often the wrong source than a wrong API key.
  • Timezones. MindBody returns site-local datetimes without offsets. Store the site timezone alongside and convert at the boundary; mixing UTC assumptions causes bookings to land on the wrong day.
  • Pagination is not optional. GetClasses, GetClients, GetAppointments all paginate. Looping until an empty page is the only safe pattern.
  • Errors are two-layered. You must handle both SOAP faults (SoapFault thrown by the transport) and MindBody's own Status/ErrorCode in the response body. Wrap both in one exception type in your gateway.
  • Rate limits and bursts. Batch writes will get throttled. Add retry-with-backoff in the gateway, and queue bulk operations (e.g. a ClientSync queue) rather than looping in a request cycle.
  • Debugging. Turn on SOAP tracing and log the last request XML and response XML on failure. With no docs, the raw XML is the fastest way to see which fields MindBody actually returned.
  • Extension points. Override the service definition in app/config/services.yml or decorate the bundle's service with your own; add compiler passes to inject a custom HTTP/SOAP client. This is the intended way to fix behaviour without patching vendor code.
  • Longevity. With 4 stars and 0 dependents, assume no upstream maintenance. Pin the exact version in composer.json, vendor the source if necessary, and budget for migrating to the MindBody REST API (v6) or a maintained client.
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.
unabomber/timezone
delatbabel/contacts
astritzeqiri/g-recaptcha
kevinongko/laravel-genode
developeruz/laravel-analytics
robbiep/afterthedeadline
frankkessler/incontact-laravel-oauth2-rest
jlxh/laravel-userlog
davidmgilo/timetables
qylinfly/role-permission
reflect-digital/conduit
takashato/laravel-vietqr
aitor24/laralang
kraenzle-ritter/entity-relations
dindigital/din-image
pomirleanu/image-colors
sawmainek/laravel-api-generator
delatbabel/jsonresponses
mouhamedfd/permissions-generator
eduplus/qr