Installation:
composer require devtrw/parse-bundle
Ensure your AppKernel.php includes the bundle:
$bundles[] = new Devtrw\ParseBundle\DevtrwParseBundle();
Configuration:
Add Parse credentials to config/packages/devtrw_parse.yaml:
devtrw_parse:
application_id: 'YOUR_APP_ID'
rest_api_key: 'YOUR_REST_API_KEY'
master_key: 'YOUR_MASTER_KEY' # Optional, for admin operations
First Use Case:
Fetch a Parse class (e.g., Post) in a controller:
use Devtrw\ParseBundle\Service\ParseService;
class PostController extends AbstractController
{
public function index(ParseService $parseService)
{
$posts = $parseService->getClass('Post')->find();
return $this->json($posts);
}
}
CRUD Operations:
Use the ParseService to interact with Parse classes:
// Create
$post = $parseService->getClass('Post')->create(['title' => 'Hello', 'content' => 'World']);
// Read
$posts = $parseService->getClass('Post')->find(['title' => 'Hello']);
// Update
$post->set('content', 'Updated!')->save();
// Delete
$post->delete();
Querying: Chain query methods for complex filters:
$posts = $parseService->getClass('Post')
->where('author', 'user123')
->greaterThan('createdAt', '2023-01-01')
->limit(10)
->find();
File Handling:
Upload/download files via ParseFile:
$file = $parseService->getFile('profile.jpg', file_get_contents('path/to/file'));
$file->save();
// Download later
$file->getContent();
Event Hooks:
Subscribe to Parse events (e.g., beforeSave) via the ParseEventDispatcher:
$dispatcher = $parseService->getEventDispatcher();
$dispatcher->addListener('beforeSave', function ($event) {
$object = $event->getObject();
$object->set('updatedAt', new \DateTime());
});
Symfony Forms: Bind Parse objects to Symfony forms for validation:
$form = $this->createForm(PostType::class, $post);
if ($form->isSubmitted() && $form->isValid()) {
$post->save(); // Uses ParseService under the hood
}
API Versioning: Override the default API version in config:
devtrw_parse:
api_version: '1.16.0' # Default is '1.13.0'
Caching: Cache frequent queries using Symfony’s cache system:
$cacheKey = 'posts:user123';
$posts = $this->cache->get($cacheKey, function () use ($parseService) {
return $parseService->getClass('Post')->where('author', 'user123')->find();
});
Testing:
Use the ParseService in tests with a mock client:
$parseService = $this->createMock(ParseService::class);
$parseService->method('getClass')->willReturn($mockClass);
Deprecation Warnings: Parse.com’s API is deprecated. Use this bundle only for legacy projects or as a learning tool. Migrate to Parse Server or Back4App for production.
Rate Limits: Parse.com enforces strict rate limits. Implement exponential backoff for retries:
try {
$result = $parseService->getClass('Post')->find();
} catch (RateLimitException $e) {
sleep($e->getRetryAfter());
retry();
}
Master Key Exposure:
Avoid committing master_key to version control. Use environment variables:
# .env
PARSE_MASTER_KEY=your_master_key_here
Class Name Collisions: Parse class names are case-sensitive. Ensure consistency between Laravel and Parse:
// Laravel model: Post
// Parse class: "Post" (not "posts" or "POST")
Enable Debug Mode: Toggle debug logs in config:
devtrw_parse:
debug: true # Logs all API requests/responses
Common Errors:
InvalidQueryException: Validate query syntax (e.g., where() conditions).ConnectionException: Check application_id/api_key and network connectivity.ClassNotFoundException: Ensure the Parse class exists and is spelled correctly.Stuck Queries: Parse queries may hang on malformed input. Validate data before sending:
$data = ['title' => 'Test', 'content' => null]; // Ensure no invalid types
Custom Clients:
Extend ParseClient to add custom endpoints:
class CustomParseClient extends ParseClient
{
public function customEndpoint($path, $data = [])
{
return $this->request('POST', "/1/custom/{$path}", $data);
}
}
Event Subscribers:
Create subscribers for Parse events (e.g., afterDelete):
class PostSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return ['afterDelete' => 'onPostDelete'];
}
public function onPostDelete(ParseEvent $event)
{
// Log or trigger side effects
}
}
Model Bindings: Bind Laravel models to Parse classes dynamically:
$parseService->bindModel(Post::class, 'Post'); // Maps Post model to Parse "Post" class
Middleware: Add middleware to transform requests/responses:
$parseService->addMiddleware(function ($request) {
$request->setHeader('X-Custom-Header', 'value');
});
How can I help you explore Laravel packages today?