Skip to content

Conversation

@binaryk
Copy link
Collaborator

@binaryk binaryk commented Aug 26, 2025

Version 10.x

🚀 Major Features

Model Context Protocol (MCP) Integration

Laravel Restify now provides seamless integration with the Model Context Protocol (MCP), allowing AI agents to interact with your REST API resources through structured tool interfaces. Transform your repositories into tools for AI agents to consume!

Quick Setup:

use Binaryk\LaravelRestify\MCP\RestifyServer;
use Laravel\Mcp\Facades\Mcp;

// Web-based MCP server with authentication
Mcp::web('restify', RestifyServer::class)
    ->middleware(['auth:sanctum'])
    ->name('mcp.restify');

Key Benefits: AI-Ready APIs, Zero Configuration, Built-in Security, Web & Terminal Access

📖 Complete MCP Documentation →

Lazy Relationship Loading for Fields

Fields can now be configured to lazy load relationships, preventing N+1 queries for computed attributes:

field('profileTagNames', fn() => $this->model()->profileTagNames)
    ->lazy('tags'),

📖 Lazy Loading Documentation →

JOIN Optimization for BelongsTo Search

Performance optimization replacing slow subqueries with efficient JOIN operations. Enable via configuration:

// config/restify.php
'search' => [
    'use_joins_for_belongs_to' => env('RESTIFY_USE_JOINS_FOR_BELONGS_TO', false),
],

📖 Performance Optimization Guide →

Repository Index Caching

Powerful caching system for repository index requests that can improve response times by orders of magnitude. Features smart cache key generation, automatic invalidation, and support for all major cache stores.

# Enable in .env
RESTIFY_REPOSITORY_CACHE_ENABLED=true
RESTIFY_REPOSITORY_CACHE_TTL=300
RESTIFY_REPOSITORY_CACHE_STORE=redis

Key Features:

  • Zero Configuration: Works out of the box with any cache store
  • Smart Invalidation: Automatically clears cache on model changes
  • User-Aware: Respects authorization and user permissions
  • Test Safe: Disabled by default in test environment
  • Store Agnostic: Works with Redis, Database, File, and Memcached stores

Performance Impact:

  • Complex queries: 50-90% faster response times
  • Large datasets: Significant database load reduction
  • Pagination: Near-instant subsequent page loads
// Repository-specific configuration
class PostRepository extends Repository {
    public static int $cacheTtl = 600; // 10 minutes
    public static array $cacheTags = ['posts', 'content'];
}

📖 Repository Caching Documentation →

Enhanced Field Methods

New and improved field methods with flexible signatures:

  • searchable() - Unified flexible signature with multiple argument support
  • matchable() - Various match types and advanced filtering scenarios
  • sortable() - Custom columns and conditional sorting

Comprehensive Field Validation Methods

Fields now include 60+ validation methods for streamlined form validation without manually writing Laravel validation rules:

// Basic validations
field('email')->required()->email(),
field('age')->integer()->min(18)->max(100),
field('password')->string()->min(8)->confirmed(),

// Advanced validations  
field('username')->alphaDash()->uniqueRule('users'),
field('website')->url()->nullable(),
field('birthday')->date()->before('today'),
field('role')->in(['admin', 'user', 'moderator']),
field('ip_address')->ip(),
field('uuid')->uuid(),
field('json_data')->json(),

// Conditional validations
field('phone')->requiredIf('contact_method', 'phone'),
field('company')->requiredWith(['is_business']),
field('start_date')->after('created_at'),
field('end_date')->afterOrEqual('start_date'),

Available Methods: required(), nullable(), email(), numeric(), integer(), boolean(), string(), array(), url(), uuid(), ip(), ipv4(), ipv6(), min(), max(), between(), uniqueRule(), exists(), confirmed(), password(), regex(), size(), accepted(), json(), alpha(), alphaNum(), alphaDash(), date(), datetime(), dateFormat(), after(), afterOrEqual(), before(), beforeOrEqual(), different(), same(), filled(), present(), isFile(), isImage(), in(), notIn(), requiredIf(), requiredUnless(), requiredWith(), requiredWithAll(), requiredWithout(), requiredWithoutAll(), multipleOf(), timezone(), currentPassword(), macAddress(), endsWith(), startsWith()

Custom Search Callbacks for BelongsTo Relations

BelongsTo fields now support custom search callbacks for complete control over search behavior:

BelongsTo::make('user')->searchable(function ($query, $request, $value, $field, $repository) {
    return $query->whereHas('user', function ($q) use ($value) {
        $q->where('name', 'ilike', "%{$value}%")
          ->orWhere('email', 'ilike', "%{$value}%");
    });
})

The callback receives all necessary parameters with the query as the first parameter for maximum flexibility.

📖 Field Methods Documentation →

⚠️ Breaking Changes

Default Search Behavior Change

Repositories no longer search by primary key (ID) by default when no searchable fields are defined.

Migration Path:

public static function searchables(): array {
    return empty(static::$search) ? [static::newModel()->getKeyName()] : static::$search;
}

📖 Complete Migration Guide →

🔧 Technical Improvements

  • Scout Integration: Enhanced error handling and graceful degradation
  • Column Qualification: Improved handling for JOIN operations
  • SearchablesCollection: Fixed string callable handling
  • Configuration: New options with environment variable support

📚 Documentation & Resources

@what-the-diff
Copy link

what-the-diff bot commented Aug 26, 2025

PR Summary

  • API Documentation Update: The documentation of our application programming interface (API) is enhanced with new sections detailing how to sort data fields, including how to enable, disable, and conditionally manage this functionality.

  • Modified Method for Mapping Columns: The 'mapColumnToRestifyField' method has been updated to now return a nullable string, this means it might not always return a value when called.

  • Command Enhancements for Policies: A new method has been added known as 'replaceUserImport', optimising the code by preventing unnecessary repetitions of User model imports in policy stubs.

  • Repository Command Improvements: Enhancements include a verification for the force option (ensures an override when confirmed by the user) & improved handling of namespaces, eliminating any redundant slashes.

  • Upgraded Sortable Functionality: Sorting features have been broadened to use callable conditions, allowing dynamic sorting based on the user's request context.

  • Refactored Method for Sorting: The 'mapIntoSortable' method has been adjusted to allow for conditional sorting when compiling related fields.

  • Removed Redundant Traits: Unused features from the 'BelongsTo' and 'HasOne' classes have been removed to simplify code.

  • Superior Stub Generation: To improve maintainability, the setup command has been modified to utilise command calls when creating repositories & policies.

  • Advanced Sorting Logic: The sort collection filters now consider the request object for dynamic field sorting.

  • General Code Enhancements: Secondary updates have improved the robustness and type-safety of various function signatures.

  • Better Formatting in Repository.php: Existing methods within Repository.php have been reformatted for clearer readability, no effects to actual operations.

  • Efficient InteractWithSearch.php: The collectSorts method is streamlined by introducing new methods for easier sorting procedures, and ensuring type integrity.

  • New Test for Sortable Fields: SortableFieldIntegrationTest.php is introduced to validate the functionality of sortable fields, ensuring its operation.

  • Tested Sortable Features in Field Class: New test cases confirm the activeness of sortable fields, and check if fields can be toggled to be sortable.

  • PostRepository Update: A static array called $sort has been included to provide predefined sorting preferences to the repository.

binaryk and others added 13 commits August 27, 2025 15:39
* fix: related fields laoded from index

* Fix styling

* fix: no index in repository

* Fix styling

* fix: wip

* Fix styling

* Fix styling

* fix: wip

---------

Co-authored-by: binaryk <binaryk@users.noreply.github.com>
* fix: adding search using lazy loading for belongs to

* Fix styling

* Fix styling

* fix: wip

* fix: wip

---------

Co-authored-by: binaryk <binaryk@users.noreply.github.com>
@binaryk binaryk changed the title 9.12.0 10.0 Aug 28, 2025
binaryk and others added 2 commits August 28, 2025 16:43
* fix: cache implementation

* Fix styling

---------

Co-authored-by: binaryk <binaryk@users.noreply.github.com>
@binaryk binaryk merged commit 4a6ed28 into 10.x Aug 28, 2025
49 checks passed

case 'integer':
case 'bigint':
case 'double':
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why move?

if (empty($modelClass)) {
throw new InvalidArgumentException('Model class cannot be empty');
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be a good idea to also check that the sent in class string is actually registered / a valid class?

Does it need to be an Eloquent Model?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants