1. Go to this page and download the library: Download mawena/maravel 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/ */
mawena / maravel example snippets
use App\Http\Controllers\API\AuthController;
use App\Http\Controllers\API\UserController;
use Illuminate\Support\Facades\Route;
Route::controller(AuthController::class)->group(function () {
Route::post("auth/login", "login");
Route::middleware('auth:sanctum')->group(function () {
Route::prefix("/auth")->name("auth.")->group(function () {
Route::get('data', "data")->name("data");
Route::delete('logout', "logout")->name("logout");
});
// Route pour changer le mot de passe (accessible même si password_change_>name('show');
Route::put('/{id}', 'update')->name('update');
Route::delete('/{id}', 'destroy')->name('destroy');
});
// Routes supplémentaires sous autorisation
});
});
});
protected $big_integer_casts = ['views_count', 'total_sales'];
// Résultat dans toArray() :
// 'views_count' => 1500000 // Converti en int
// 'views_count_fr' => '1 500 000' // Version formatée
use Illuminate\Database\Eloquent\Model;
use Maravel\Models\ModelTrait;
class Product extends Model
{
use ModelTrait; // Utilisation directe du trait
protected $dateCasts = ['launched_at' => 'd/m/Y'];
protected $moneyCasts = ['price'];
}
namespace App\Models;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use Maravel\Models\AuthenticatableBase;
class User extends AuthenticatableBase
{
use HasApiTokens, Notifiable;
protected $fillable = [
'name',
'email',
'password',
'activated',
'password_change_ile`)
protected $enumCasts = [
[
'colum_name' => 'activated',
'additional_column_name' => 'activated_fr',
'choices' => [
1 => 'Oui',
0 => 'Non',
],
],
[
'colum_name' => 'password_change_ écrire ici.
}
// Route : PUT /api/users/update-password
// Corps de la requête :
{
"current_password": "ancien_mot_de_passe",
"new_password": "nouveau_mot_de_passe",
"new_password_confirmation": "nouveau_mot_de_passe"
}
// Réponse en cas de succès :
{
"message": "Mot de passe modifié avec succès",
"user": { ... }
}
->withMiddleware(function (Middleware $middleware) {
// Middleware Maravel pour vérifier le statut du compte
$middleware->alias([
'account.status' => \Maravel\Http\Middleware\AccountStatusMiddleware::class,
]);
})
// Sur un groupe de routes
Route::middleware(['auth:sanctum', 'account.status'])->group(function () {
Route::apiResource('posts', PostController::class);
Route::apiResource('products', ProductController::class);
});
// Sur une route spécifique
Route::get('/dashboard', [DashboardController::class, 'index'])
->middleware(['auth:sanctum', 'account.status']);
$user = User::find(5);
$user->activated = false;
$user->save();
// L'utilisateur ne pourra plus accéder aux routes protégées par account.status
$user = User::find(5);
$user->password_change_ son mot de passe avant d'accéder aux routes protégées
namespace App\Policies;
use Maravel\Policies\BasePolicy;
use App\Models\User;
use App\Models\Product;
class ProductPolicy extends BasePolicy
{
// Le sujet pour les vérifications de permissions
protected string $subject = 'product';
// Méthode before() pour vérifications globales
public function before(User $user, string $ability): ?bool
{
// Les super-admins ont tous les droits
if ($user->isAdmin()) {
return true;
}
return null; // Continuer les vérifications normales
}
// Permission personnalisée
public function publish(User $user, Product $product): bool
{
return $this->checkCustomPermission($user, ['publish'], $this->subject)
&& $product->user_id === $user->id;
}
}
use App\Models\Product;
use App\Policies\ProductPolicy;
protected $policies = [
Product::class => ProductPolicy::class,
];
use Maravel\Http\Traits\CustomResponseTrait;
class MyController extends Controller
{
use CustomResponseTrait;
public function index()
{
$data = ['items' => [...]];
return $this->responseOk($data, ['Success'], 200);
}
public function error()
{
// 422 = Unprocessable Entity (erreur de validation)
return $this->responseError(['field' => ['Error message']], 422);
}
}
use Maravel\Http\Traits\ControllerHelperTrait;
class MyController extends Controller
{
use ControllerHelperTrait;
public function index(Request $request)
{
$query = Product::query();
// Ajouter des filtres
$query = $this->queryFilter($query, $request->all(), 'Product');
// Ajouter recherche
$query = $this->querySearch($query, ['name', 'description'], $request->search);
// Ajouter relations
$query = $this->queryRelationAdd($query, $request->all(), 'Product');
return $query->get();
}
}
// Dans votre modèle, définissez des méthodes "reducer"
class Product extends ModelBase
{
/**
* Reducer pour ajouter des statistiques
*/
public function statsReducer($collection, $requestData)
{
// Ajouter des statistiques calculées
$collection->map(function ($item) {
$item->total_revenue = $item->price * $item->sold_count;
return $item;
});
return $collection;
}
/**
* Reducer pour filtrer selon l'utilisateur
*/
public function userFilterReducer($collection, $requestData)
{
$userId = $requestData['user_id'] ?? null;
if ($userId) {
return $collection->where('user_id', $userId)->values();
}
return $collection;
}
}
// Utilisation dans la requête API :
// GET /api/products?reduce_stats=true
// GET /api/products?reduce_user_filter=true&user_id=5
// Le système cherchera automatiquement les méthodes suffixées par "Reducer"
use Maravel\Http\Traits\PermissionCheckerTrait;
class MyController extends Controller
{
use PermissionCheckerTrait;
public function index(Request $request)
{
$user = $request->user();
if (!$this->canRead('product', $user)) {
return response()->json(['error' => 'Unauthorized'], 403);
}
if ($this->isAdmin($user)) {
// Logique admin
}
return Product::all();
}
}
// Sur un groupe de routes
Route::middleware(['auth:sanctum', 'maravel.fields'])->group(function () {
Route::apiResource('products', ProductController::class);
Route::apiResource('users', UserController::class);
});
// Sur une route spécifique
Route::get('/users/{id}', [UserController::class, 'show'])
->middleware('maravel.fields');
// Ancien : $user->profile = 'admin';
$user->assignRole('admin');
$user->assignRole('admin'); // par nom
$user->assignRole($role, 5); // par modèle, par id
$user->syncRoles('manager', 'comptable'); // remplace tous les rôles
$user->removeRole('manager');
$user->isAdmin(); // au moins un rôle is_super_admin
$user->hasRole('manager');
$user->hasPermissionTo('validate', 'user'); // tient compte de manage / all
$user->roles; // relation
$user->ability_rules; // règles CASL calculées
class ProductPolicy extends BasePolicy
{
protected $modelName = "product"; // les actions read/create/update/delete sont gérées
}
use Maravel\Http\Traits\PermissionCheckerTrait;
public function index(Request $request)
{
if (!$this->canRead('product', $request->user())) {
abort(403, 'Unauthorized');
}
return Product::all();
}
class ProductController extends APIController
{
// Validation personnalisée
protected function storeManualValidationsFunction(array $data): array
{
if ($data['price'] > 10000) {
return ['price' => ['Le prix ne peut pas dépasser 10000']];
}
return [];
}
// Avant la création
protected function storeBeforeCreateFunction(array $data): array
{
$data['slug'] = Str::slug($data['name']);
return $data;
}
// Après la création
protected function storeAfterCreateFunction($model): void
{
// Envoyer un email
Mail::to('[email protected]')->send(new ProductCreated($model));
}
// Avant le commit en base de données
protected function storeBeforeCommitFunction($model): void
{
// Logique métier
}
// Après le commit
protected function storeAfterCommitFunction($model): void
{
// Créer des enregistrements liés
$model->history()->create(['action' => 'created']);
}
}
class ProductController extends APIController
{
// Validation personnalisée
protected function updateManualValidationsFunction(array $data, $model): array
{
if (isset($data['price']) && $data['price'] < $model->cost) {
return ['price' => ['Le prix ne peut pas être inférieur au coût']];
}
return [];
}
// Avant la mise à jour
protected function updateBeforeUpdateFunction(array $data, $model): array
{
if (isset($data['name'])) {
$data['slug'] = Str::slug($data['name']);
}
return $data;
}
// Après la mise à jour
protected function updateAfterUpdateFunction($model): void
{
Cache::forget("product_{$model->id}");
}
}
class ProductController extends APIController
{
// Avant la suppression
protected function deleteBeforeDeleteFunction($model): void
{
// Supprimer les fichiers associés
Storage::delete($model->images->pluck('path')->toArray());
}
// Après la suppression
protected function deleteAfterDeleteFunction($model): void
{
// Logger la suppression
Log::info("Product {$model->id} deleted");
}
}
class ProductController extends APIController
{
protected function indexManualFilter($query, array $requestData)
{
// Ajouter des filtres personnalisés complexes
if (isset($requestData['category_slug'])) {
$query->whereHas('category', function ($q) use ($requestData) {
$q->where('slug', $requestData['category_slug']);
});
}
return $query;
}
}
namespace App\Policies;
use Maravel\Policies\BasePolicy;
use App\Models\User;
use App\Models\Product;
class ProductPolicy extends BasePolicy
{
protected string $subject = 'product';
public function before(User $user, string $ability): ?bool
{
if ($user->isAdmin()) {
return true;
}
return null;
}
public function viewAny(User $user): bool
{
// Tout le monde peut voir les produits
return true;
}
public function create(User $user): bool
{
return $this->checkCustomPermission($user, ['create'], $this->subject);
}
public function update(User $user, Product $product): bool
{
return $this->checkCustomPermission($user, ['update'], $this->subject);
}
public function updatePrice(User $user, Product $product): bool
{
// Seuls les admins et managers peuvent modifier les prix
return $user->isAdmin() || $user->hasRole('manager');
}
}
namespace App\Http\Controllers\API;
use Maravel\Http\Controllers\APIController;
use App\Models\Product;
class ProductController extends APIController
{
protected string $modelClass = Product::class;
protected array $storeValidationArray = [
'name' => ' 'name' => 'string|max:255',
'description' => 'nullable|string',
'price' => 'numeric|min:0',
'cost' => 'numeric|min:0',
'stock' => 'integer|min:0',
'is_active' => 'boolean',
];
protected array $indexSearchFieldList = ['name', 'description'];
protected bool $indexCheckAbility = false; // Désactiver pour viewAny
protected function updateManualValidationsFunction(array $data, $model): array
{
// Vérifier la permission pour modifier le prix
if (isset($data['price'])) {
if (!auth()->user()->can('updatePrice', $model)) {
return ['price' => ['Vous n\'avez pas la permission de modifier le prix']];
}
}
// Vérifier que le prix est supérieur au coût
if (isset($data['price']) && $data['price'] < ($data['cost'] ?? $model->cost)) {
return ['price' => ['Le prix doit être supérieur au coût']];
}
return [];
}
protected function storeAfterCommitFunction($model): void
{
// Créer l'historique de stock
$model->stockHistory()->create([
'quantity' => $model->stock,
'type' => 'initial',
'user_id' => auth()->id(),
]);
}
}
// Pour un utilisateur "manager"
$user->ability_rules = [
[
'subject' => ['product'],
'action' => ['read', 'create', 'update'],
],
];
// Pour un utilisateur "seller"
$user->ability_rules = [
[
'subject' => ['product'],
'action' => ['read'],
],
];
bash
php artisan maravel:install
bash
php artisan db:seed --class=RolePermissionSeeder # crée le rôle "admin" (is_super_admin) + permissions de base
bash
# Modèle standard avec ModelBase
php artisan make:maravel.model Product
# Modèle User avec AuthenticatableBase (pour l'authentification)
php artisan make:maravel.model User --authenticatable