11# PHP CRUD API Generator
22
3+ [ ![ Latest Stable Version] ( https://poser.pugx.org/bitshost/php-crud-api-generator/v/stable )] ( https://packagist.org/packages/bitshost/php-crud-api-generator )
4+ [ ![ Total Downloads] ( https://poser.pugx.org/bitshost/php-crud-api-generator/downloads )] ( https://packagist.org/packages/bitshost/php-crud-api-generator )
5+ [ ![ License] ( https://poser.pugx.org/bitshost/php-crud-api-generator/license )] ( https://packagist.org/packages/bitshost/php-crud-api-generator )
6+ [ ![ PHP Version] ( https://img.shields.io/badge/php-%3E%3D8.0-blue.svg )] ( https://php.net )
7+
38Expose your MySQL/MariaDB database as a secure, flexible, and instant REST-like API.
49Features optional authentication (API key, Basic Auth, JWT, OAuth-ready),
510OpenAPI (Swagger) docs, and zero code generation.
611
712---
813
9- ## 🚀 ## 🚀 Features
14+ ## 🚀 Features
1015
1116- Auto-discovers tables and columns
1217- Full CRUD endpoints for any table
1318- ** Bulk operations** - Create or delete multiple records efficiently
1419- Configurable authentication (API Key, Basic Auth, JWT, or none)
20+ - ** Rate limiting** - Prevent API abuse with configurable request limits
21+ - ** Request logging** - Comprehensive logging for debugging and monitoring
1522- ** Advanced query features:**
1623 - ** Field selection** - Choose specific columns to return
1724 - ** Advanced filtering** - Support for multiple comparison operators (eq, neq, gt, gte, lt, lte, like, in, notin, null, notnull)
@@ -25,6 +32,8 @@ OpenAPI (Swagger) docs, and zero code generation.
2532- PHPUnit tests and extensible architecture
2633
2734📖 ** [ See detailed enhancement documentation →] ( ENHANCEMENTS.md ) **
35+ 📖 ** [ Rate Limiting Documentation →] ( docs/RATE_LIMITING.md ) **
36+ 📖 ** [ Request Logging Documentation →] ( docs/REQUEST_LOGGING.md ) **
2837
2938---
3039
@@ -68,14 +77,55 @@ return [
6877 'jwt_secret' => 'YourSuperSecretKey',
6978 'jwt_issuer' => 'yourdomain.com',
7079 'jwt_audience' => 'yourdomain.com',
71- 'oauth_providers' => [
72- // 'google' => ['client_id' => '', 'client_secret' => '', ...]
73- ]
80+
81+ // Rate limiting (recommended for production)
82+ 'rate_limit' => [
83+ 'enabled' => true,
84+ 'max_requests' => 100, // 100 requests
85+ 'window_seconds' => 60, // per 60 seconds (1 minute)
86+ ],
87+
88+ // Request logging (recommended for production)
89+ 'logging' => [
90+ 'enabled' => true,
91+ 'log_dir' => __DIR__ . '/../logs',
92+ 'log_level' => 'info', // debug, info, warning, error
93+ ],
7494];
7595```
7696
7797---
7898
99+ ## 🔒 Security Setup (Production)
100+
101+ ⚠️ ** IMPORTANT:** This framework ships with ** example credentials for development** .
102+ You ** MUST** change these before deploying to production!
103+
104+ ### Quick Security Setup:
105+
106+ ``` bash
107+ # 1. Generate secure secrets (JWT secret + API keys)
108+ php scripts/generate_secrets.php
109+
110+ # 2. Update config/api.php with generated secrets
111+
112+ # 3. Create admin user in database
113+ php scripts/create_user.php admin admin@yoursite.com YourSecurePassword123! admin
114+ ```
115+
116+ ### What to Change:
117+
118+ - [ ] ` jwt_secret ` - Generate with: ` php scripts/generate_jwt_secret.php `
119+ - [ ] ` api_keys ` - Use long random strings (64+ characters)
120+ - [ ] Default admin password in ` sql/create_api_users.sql `
121+ - [ ] Database credentials in ` config/db.php `
122+
123+ 📖 ** Full security guide:** [ docs/AUTHENTICATION.md] ( docs/AUTHENTICATION.md )
124+
125+ ---
126+
127+ ---
128+
79129## 🔐 Authentication Modes
80130
81131- ** No auth:** ` 'auth_enabled' => false `
@@ -344,11 +394,18 @@ get:
344394## 🛡️ Security Notes
345395
346396- **Enable authentication for any public deployment!**
397+ - **Enable rate limiting in production** to prevent abuse
398+ - **Enable request logging** for security auditing and debugging
347399- Never commit real credentials—use ` .gitignore` and example configs.
348400- Restrict DB user privileges.
349401- **Input validation**: All user inputs (table names, column names, IDs, filters) are validated to prevent SQL injection and invalid queries.
350402- **Parameterized queries**: All database queries use prepared statements with bound parameters.
351403- **RBAC enforcement**: Role-based access control is enforced at the routing level before any database operations.
404+ - **Rate limiting**: Configurable request limits prevent API abuse and DoS attacks.
405+ - **Sensitive data redaction**: Passwords, tokens, and API keys are automatically redacted from logs.
406+
407+ 📖 **[Rate Limiting Documentation →](docs/RATE_LIMITING.md)**
408+ 📖 **[Request Logging Documentation →](docs/REQUEST_LOGGING.md)**
352409
353410---
354411
@@ -360,9 +417,77 @@ get:
360417
361418---
362419
420+ # ## 🔗 Working with Related Data (Client-Side Joins)
421+
422+ Your API provides all the data you need - it's up to the client to decide how to combine it. This approach gives you maximum flexibility and control.
423+
424+ **Current approach:** Fetch related data in separate requests and combine on the client side.
425+
426+ # ### Quick Example: Get User with Posts
427+
428+ ` ` ` javascript
429+ // 1. Fetch user
430+ const user = await fetch('/api.php?action=read&table=users&id=123')
431+ .then(r => r.json());
432+
433+ // 2. Fetch user's posts
434+ const posts = await fetch('/api.php?action=list&table=posts&filter=user_id:123')
435+ .then(r => r.json());
436+
437+ // 3. Combine however you want
438+ const userData = {
439+ ...user,
440+ posts: posts.data
441+ };
442+ ` ` `
443+
444+ # ### Optimization: Use IN Operator for Batch Fetching
445+
446+ ` ` ` javascript
447+ // Get multiple related records in one request
448+ const postIds = '1|2|3|4|5'; // IDs from previous query
449+ const comments = await fetch(
450+ ` /api.php?action=list&table=comments&filter=post_id:in:${postIds}`
451+ ).then(r => r.json());
452+
453+ // Group by post_id on client
454+ const commentsByPost = comments.data.reduce((acc, comment) => {
455+ acc[comment.post_id] = acc[comment.post_id] || [];
456+ acc[comment.post_id].push(comment);
457+ return acc;
458+ }, {});
459+ ```
460+
461+ #### Parallel Fetching for Performance
462+
463+ ``` javascript
464+ // Fetch multiple resources simultaneously
465+ const [user , posts , comments ] = await Promise .all ([
466+ fetch (' /api.php?action=read&table=users&id=123' ).then (r => r .json ()),
467+ fetch (' /api.php?action=list&table=posts&filter=user_id:123' ).then (r => r .json ()),
468+ fetch (' /api.php?action=list&table=comments&filter=user_id:123' ).then (r => r .json ())
469+ ]);
470+
471+ // All requests happen at once - much faster!
472+ ```
473+
474+ 📖 ** [ See complete client-side join examples →] ( docs/CLIENT_SIDE_JOINS.md ) **
475+
476+ ** Why this approach?**
477+ - ✅ Client decides what data to fetch and when
478+ - ✅ Easy to optimize with caching and parallel requests
479+ - ✅ Different clients can have different data needs
480+ - ✅ Standard REST API practice
481+ - ✅ No server-side complexity for joins
482+
483+ ** Future:** Auto-join/expand features may be added based on user demand.
484+
485+ ---
486+
363487## 🗺️ Roadmap
364488
365- - Relations / Linked Data (auto-join, populate, or expand related records)
489+ - ** Client-side joins** ✅ (Current - simple and flexible!)
490+ - Relations / Linked Data (auto-join, populate, or expand related records) - * Future, based on demand*
366491- API Versioning (when needed)
367492- OAuth/SSO (if targeting SaaS/public)
368493- More DB support (Postgres, SQLite, etc.)
0 commit comments