PHP code example of ibekzod / microcrud

1. Go to this page and download the library: Download ibekzod/microcrud library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

ibekzod / microcrud example snippets




namespace App\Models;

use Microcrud\Abstracts\Model;

class Product extends Model
{
    protected $fillable = [
        'name',
        'description',
        'price',
        'stock',
        'category_id',
        'is_active'
    ];

    // Define relationships as usual
    public function category()
    {
        return $this->belongsTo(Category::class);
    }
}



namespace App\Services;

use Microcrud\Abstracts\Service;
use App\Models\Product;

class ProductService extends Service
{
    protected $model = Product::class;

    // That's it! You now have full CRUD functionality
    // Optionally enable advanced features:
    // protected $enableCache = true;
    // protected $useJob = true;
}



namespace App\Http\Controllers;

use Microcrud\Http\CrudController;
use App\Services\ProductService;

class ProductController extends CrudController
{
    protected $service = ProductService::class;

    // Optionally override specific methods for custom logic
}

// routes/api.php

// Single resource
Route::microcrud('products', ProductController::class);

// Multiple resources
Route::microcruds([
    'products' => ProductController::class,
    'categories' => CategoryController::class,
    'orders' => OrderController::class,
]);

// routes/api.php
Route::apiResource('products', ProductController::class);
Route::post('products/{id}/restore', [ProductController::class, 'restore']);
Route::post('products/bulk', [ProductController::class, 'bulkAction']);

// Core CRUD operations
$service->index($data);        // List with filters
$service->show($id);           // Get single item
$service->create($data);       // Create new item
$service->update($id, $data);  // Update existing item
$service->delete($id);         // Delete (soft/hard)
$service->restore($id);        // Restore soft-deleted

// Bulk operations
$service->bulkCreate($items);
$service->bulkUpdate($items);
$service->bulkDelete($ids);
$service->bulkRestore($ids);

// Query manipulation
$service->setQuery($query);
$service->getQuery();
$service->applyDynamicFilters($query, $data);

// Validation
$service->indexRules();
$service->createRules();
$service->updateRules();

// Cache control
$service->enableCache();
$service->clearCache();

class CrudController extends ApiBaseController
{
    // All methods return formatted JSON responses:
    index()      → 200 OK (paginated list)
    show($id)    → 200 OK (single item)
    create()     → 201 Created
    update($id)  → 202 Accepted
    delete($id)  → 202 Accepted
    restore($id) → 202 Accepted
    bulkAction() → 202 Accepted
}

class ItemResource extends JsonResource
{
    // Automatically:
    // - Formats dates (Y-m-d H:i:s)
    // - Converts _id fields to nested objects
    // - Handles relationships

    public function toArray($request)
    {
        return $this->forModel();
    }
}

// Single resource
Route::microcrud('products', ProductController::class);

// Multiple resources
Route::microcruds([
    'products' => ProductController::class,
    'categories' => CategoryController::class,
]);

Route::prefix('v1')->middleware(['auth:api'])->group(function () {
    Route::microcruds([
        'products' => ProductController::class,
        'orders' => OrderController::class,
    ]);
});

// Example: Add aggregation for grouped queries
class ApartmentService extends Service
{
    public function beforeIndex()
    {
        $data = $this->getData();
        $query = $this->getQuery();

        if (!empty($data['group_bies'])) {
            $table = $this->getModelTableName();
            $query->selectRaw("COUNT(*) as apartment_count")
                  ->selectRaw("SUM(price) as total_value")
                  ->selectRaw("AVG(price) as avg_price");
        }

        $this->setQuery($query);
        return parent::beforeIndex();
    }
}

class Apartment extends Model
{
    public function block()
    {
        return $this->belongsTo(Block::class);
    }
}

class Block extends Model
{
    public function manager()
    {
        return $this->belongsTo(User::class, 'manager_id');
    }
}

class ProductService extends Service
{
    protected $model = Product::class;

    // Override to customize rules
    public function createRules($rules = [], $replace = false)
    {
        return parent::createRules([
            'name' => 'tion updateRules($rules = [], $replace = false)
    {
        return parent::updateRules([
            'name' => 'sometimes|string|max:255',
            'price' => 'sometimes|numeric|min:0',
            'stock' => 'sometimes|integer|min:0',
        ], $replace);
    }
}

class ProductService extends Service
{
    protected $model = Product::class;
    protected $enableCache = true;
    protected $cacheExpiration = 3600; // seconds

    // Cache is automatically:
    // ✓ Created on read operations
    // ✓ Tagged by model name
    // ✓ Invalidated on create/update/delete
    // ✓ Scoped to query parameters
}

$service->enableCache();
$service->disableCache();
$service->clearCache();

class ProductService extends Service
{
    protected $model = Product::class;
    protected $useJob = true;
    protected $queueName = 'products';

    // Now create/update operations are queued automatically
}

// Bulk Create
POST /products/bulk
{
  "action": "create",
  "data": [
    {"name": "Product 1", "price": 100},
    {"name": "Product 2", "price": 200},
    {"name": "Product 3", "price": 300}
  ]
}

// Bulk Update
POST /products/bulk
{
  "action": "update",
  "data": [
    {"id": 1, "price": 150},
    {"id": 2, "price": 250}
  ]
}

// Bulk Delete
POST /products/bulk
{
  "action": "delete",
  "ids": [1, 2, 3, 4, 5]
}

// Bulk Restore
POST /products/bulk
{
  "action": "restore",
  "ids": [1, 2, 3]
}

// Bulk Show
POST /products/bulk
{
  "action": "show",
  "ids": [1, 2, 3]
}

// In your service
$service->delete($id);              // Soft delete
$service->delete($id, true);        // Force delete
$service->restore($id);             // Restore

class ProductService extends Service
{
    protected $model = Product::class;

    // Before hooks (can modify data)
    public function beforeCreate($data)
    {
        $data['sku'] = 'PRD-' . strtoupper(uniqid());
        $data['slug'] = Str::slug($data['name']);
        return $data;
    }

    public function beforeUpdate($id, $data)
    {
        Log::info("Updating product {$id}", $data);
        return $data;
    }

    // After hooks (receive created/updated item)
    public function afterCreate($item)
    {
        Cache::tags(['products'])->flush();
        event(new ProductCreated($item));
        return $item;
    }

    public function afterUpdate($item)
    {
        event(new ProductUpdated($item));
        return $item;
    }

    public function afterDelete($item)
    {
        Storage::deleteDirectory("products/{$item->id}");
        return $item;
    }

    public function afterRestore($item)
    {
        event(new ProductRestored($item));
        return $item;
    }

    public function afterIndex()
    {
        // Called after listing items
    }
}



namespace App\Http\Resources;

use Microcrud\Responses\ItemResource;

class ProductResource extends ItemResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'description' => $this->description,
            'price' => [
                'amount' => $this->price,
                'formatted' => '$' . number_format($this->price, 2),
                'currency' => 'USD',
            ],
            'stock' => [
                'quantity' => $this->stock,
                'status' => $this->stock > 0 ? 'in_stock' : 'out_of_stock',
                'low_stock' => $this->stock < 10,
            ],
            'category' => new CategoryResource($this->whenLoaded('category')),
            'images' => ImageResource::collection($this->whenLoaded('images')),
            'is_active' => (bool) $this->is_active,
            'timestamps' => [
                'created' => $this->created_at->toISOString(),
                'updated' => $this->updated_at->toISOString(),
            ],
        ];
    }
}

class ProductController extends CrudController
{
    protected $service = ProductService::class;
    protected $resource = ProductResource::class;
}

class ProductService extends Service
{
    protected $model = Product::class;
    protected $useTransaction = true; // default

    // Or disable for specific operations
    public function create($data)
    {
        $this->setIsTransactionEnabled(false);
        return parent::create($data);
    }
}

class ProductService extends Service
{
    protected $model = Product::class;

    public function index($data)
    {
        // Apply custom query before processing
        $query = $this->model::query()
            ->with(['category', 'images'])
            ->where('is_active', true)
            ->whereHas('category', function($q) {
                $q->where('active', true);
            });

        $this->setQuery($query);

        return parent::index($data);
    }
}

class ProductService extends Service
{
    protected $model = Product::class;

    public function index($data)
    {
        // Eager load relationships
        $query = $this->model::with([
            'category',
            'images',
            'reviews' => function($q) {
                $q->where('approved', true);
            }
        ]);

        $this->setQuery($query);
        return parent::index($data);
    }

    public function show($id)
    {
        $query = $this->model::with(['category', 'images', 'reviews']);
        $this->setQuery($query);
        return parent::show($id);
    }
}

$service->withoutScopes(['ActiveScope'])->index($data);
$service->withoutScopes()->index($data); // Remove all scopes

use Microcrud\Traits\ParentChildTrait;

class Category extends Model
{
    use ParentChildTrait;

    protected $fillable = ['name', 'parent_id'];
}

$category = Category::find(1);

// Get direct children
$children = $category->children;

// Get all descendants (recursive)
$allDescendants = $category->allChildren;

// Get parent
$parent = $category->parent;

// Get all descendant IDs
$ids = $category->getAllDescendantIds(); // [2, 3, 4, 5, ...]

// Get full tree from root
$tree = Category::getRootWithChildren();

$category->delete(); // Automatically deletes all children

use Microcrud\Services\Curl\Services\CurlService;

$curl = new CurlService();

// GET request
$curl->setUrl('https://api.example.com/users')
     ->setHeaders([
         'Authorization' => 'Bearer ' . $token,
         'Accept' => 'application/json',
     ])
     ->setParams(['page' => 1, 'limit' => 20]);

$response = $curl->get();

// POST request
$curl->setUrl('https://api.example.com/users')
     ->setParams([
         'name' => 'John Doe',
         'email' => '[email protected]',
     ]);

$response = $curl->post();

// Other methods
$curl->put();
$curl->patch();
$curl->delete();

// app/Http/Kernel.php
protected $routeMiddleware = [
    'locale' => \Microcrud\Middlewares\LocaleMiddleware::class,
];

// routes/api.php
Route::middleware(['locale'])->group(function () {
    Route::apiResource('products', ProductController::class);
});

protected $routeMiddleware = [
    'timezone' => \Microcrud\Middlewares\TimezoneMiddleware::class,
];

Route::middleware(['timezone'])->group(function () {
    // Your routes
});

protected $routeMiddleware = [
    'log.http' => \Microcrud\Middlewares\LogHttpRequest::class,
];

Route::middleware(['log.http'])->group(function () {
    // Your routes
});



return [
    /*
    |--------------------------------------------------------------------------
    | Database Connection
    |--------------------------------------------------------------------------
    |
    | Specify a custom database connection. Leave empty to use default.
    |
    */
    'connection' => env('MICROCRUD_DB_CONNECTION', ''),

    /*
    |--------------------------------------------------------------------------
    | Authorization
    |--------------------------------------------------------------------------
    |
    | Enable/disable authorization checks in controllers.
    |
    */
    'authorize' => env('MICROCRUD_AUTHORIZE', true),

    /*
    |--------------------------------------------------------------------------
    | Supported Locales
    |--------------------------------------------------------------------------
    |
    | List of locales supported by your application.
    |
    */
    'locales' => ['en', 'ru', 'uz'],

    /*
    |--------------------------------------------------------------------------
    | Default Locale
    |--------------------------------------------------------------------------
    |
    | The default locale for your application.
    |
    */
    'locale' => env('MICROCRUD_LOCALE', 'en'),

    /*
    |--------------------------------------------------------------------------
    | Default Timezone
    |--------------------------------------------------------------------------
    |
    | The default timezone used by TimezoneMiddleware.
    |
    */
    'timezone' => env('MICROCRUD_TIMEZONE', 'UTC'),
];



return [
    'notification' => env('DB_NOTIFICATION_SCHEMA', 'public'),
    'upload' => env('DB_UPLOAD_SCHEMA', 'public'),
    'user' => env('DB_USER_SCHEMA', 'public'),
    // Add your schemas here
];

// app/Models/Product.php
namespace App\Models;

use Microcrud\Abstracts\Model;

class Product extends Model
{
    use SoftDeletes;

    protected $fillable = [
        'name', 'slug', 'description', 'price', 'sale_price',
        'sku', 'stock', 'category_id', 'brand_id', 'is_active'
    ];

    protected $casts = [
        'price' => 'decimal:2',
        'sale_price' => 'decimal:2',
        'is_active' => 'boolean',
    ];

    public function category()
    {
        return $this->belongsTo(Category::class);
    }

    public function brand()
    {
        return $this->belongsTo(Brand::class);
    }

    public function images()
    {
        return $this->hasMany(ProductImage::class);
    }

    public function reviews()
    {
        return $this->hasMany(Review::class);
    }
}

// app/Services/ProductService.php
namespace App\Services;

use Microcrud\Abstracts\Service;
use App\Models\Product;
use Illuminate\Support\Str;

class ProductService extends Service
{
    protected $model = Product::class;
    protected $enableCache = true;
    protected $cacheExpiration = 3600;
    protected $useTransaction = true;

    public function beforeCreate($data)
    {
        $data['slug'] = Str::slug($data['name']);
        $data['sku'] = 'PRD-' . strtoupper(uniqid());
        return $data;
    }

    public function afterCreate($item)
    {
        Cache::tags(['products'])->flush();
        event(new ProductCreated($item));
        return $item;
    }

    public function createRules($rules = [], $replace = false)
    {
        return parent::createRules([
            'name' => '>price) * 100)
                    : 0,
            ],
            'inventory' => [
                'sku' => $this->sku,
                'stock' => $this->stock,
                'in_stock' => $this->stock > 0,
            ],
            'category' => new CategoryResource($this->whenLoaded('category')),
            'brand' => new BrandResource($this->whenLoaded('brand')),
            'images' => ImageResource::collection($this->whenLoaded('images')),
            'rating' => [
                'average' => round($this->reviews_avg_rating ?? 0, 1),
                'count' => $this->reviews_count ?? 0,
            ],
            'is_active' => (bool) $this->is_active,
            'created_at' => $this->created_at->toISOString(),
        ];
    }
}

// tests/Feature/ProductApiTest.php
namespace Tests\Feature;

use Tests\TestCase;
use App\Models\Product;
use App\Models\Category;

class ProductApiTest extends TestCase
{
    public function test_can_list_products()
    {
        Product::factory()->count(5)->create();

        $response = $this->getJson('/api/products');

        $response->assertStatus(200)
                 ->assertJsonStructure([
                     'success',
                     'data' => [
                         '*' => ['id', 'name', 'price']
                     ],
                     'meta'
                 ]);
    }

    public function test_can_create_product()
    {
        $category = Category::factory()->create();

        $data = [
            'name' => 'Test Product',
            'price' => 99.99,
            'stock' => 10,
            'category_id' => $category->id,
        ];

        $response = $this->postJson('/api/products', $data);

        $response->assertStatus(201)
                 ->assertJson(['success' => true]);

        $this->assertDatabaseHas('products', ['name' => 'Test Product']);
    }

    public function test_can_filter_products_by_price()
    {
        Product::factory()->create(['price' => 50]);
        Product::factory()->create(['price' => 150]);
        Product::factory()->create(['price' => 250]);

        $response = $this->getJson('/api/products?search_by_price_min=100&search_by_price_max=200');

        $response->assertStatus(200);
        $this->assertCount(1, $response->json('data'));
    }
}
bash
php artisan vendor:publish --provider="Microcrud\MicrocrudServiceProvider"
json
{
  "success": true,
  "data": {
    "id": 1,
    "name": "Laptop",
    "price": 999.99,
    "stock": 15,
    "is_active": true,
    "created_at": "2025-01-15 10:30:00",
    "updated_at": "2025-01-15 10:30:00"
  }
}