FindikEngine, Laravel mimarisinden ilham alınarak sıfırdan yazılmış, tam özellikli bir PHP MVC framework'üdür. Routing, DI Container, Auth, Validation, Mail, Event, Pagination, CLI, API Token, Çok Dilli İçerik ve daha fazlasını içerir.
Eğitim ve öğrenme amaçlıdır.
- Laravel benzeri routing (
resource,PUT/DELETE, middleware grupları) - Reflection tabanlı IoC Container + DI
- Laravel-like Request / ResponseBuilder
- Auth Facade (önbellekli, remember me, API token)
- Form Validation (20+ kural) + FormRequest
- Merkezi ExceptionHandler +
abort() - RBAC — rol & izin yönetimi
- Rate Limiting (
throttle:5,300) - Pagination (
$items->links()) - Mail (Mailable pattern, log/smtp driver)
- Event / Listener sistemi
- Soft Deletes, Model Factories
- PHPUnit test altyapısı (43 test)
- Console CLI (
php console make:controller,migrate, vb.) - Çok Dilli İçerik (blog, ürün, kategori, sayfa)
- Admin Panel (RBAC, istatistik grafikleri, log görüntüleyici)
- Frontend (blog, ürünler, statik sayfalar)
- CSRF, XSS, SQL Injection, Open Redirect, Session Fixation koruması
- CSP (nonce tabanlı), güvenlik HTTP başlıkları
- PHP 8.1+
- MySQL 5.7+ / MariaDB 10.2+
- Composer
- Apache (mod_rewrite) veya Nginx
- PHP extensions: PDO, mbstring, fileinfo, gd
# 1. Bağımlılıkları yükle
composer install
# 2. Environment dosyasını oluştur
cp .env.example .env
# 3. .env içindeki DB bilgilerini doldur
# 4. Migration + Seed çalıştır
# .env → RUN_MIGRATIONS=true, RUN_SEEDERS=true
# Sonra herhangi bir sayfayı yükle, ya da:
php console migrate
php console db:seed
# 5. Geliştirme sunucusu
php -S localhost:8000 -t publicAPP_ENV=local
APP_DEBUG=true
APP_URL=http://localhost:8000
APP_KEY=your-32-char-secret-key
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=findikengine
DB_USERNAME=root
DB_PASSWORD=
MAIL_DRIVER=log
MAIL_FROM_ADDRESS=noreply@findikengine.test
MAIL_FROM_NAME=FindikEngine
RUN_MIGRATIONS=false
RUN_SEEDERS=false| Şifre | Rol | |
|---|---|---|
admin@findikengine.test |
12345678 |
admin |
test@findikengine.test |
12345678 |
member |
findik-engine/
├── public/index.php ← Entry point
├── core/ ← Framework çekirdeği
│ ├── Application.php ← Bootstrap orkestratör
│ ├── Auth.php ← Auth facade (önbellekli)
│ ├── Cache.php ← HMAC-imzalı dosya cache
│ ├── Container.php ← IoC Container (Reflection)
│ ├── ExceptionHandler.php ← Merkezi exception yönetimi
│ ├── FormRequest.php ← Auto-validating request
│ ├── Language.php ← Çok dilli sistem singleton
│ ├── Paginator.php ← Bootstrap 5 sayfalama
│ ├── RateLimiter.php ← Rate limiter
│ ├── Request.php ← Laravel-like request
│ ├── ResponseBuilder.php ← Fluent response builder
│ ├── Route.php ← Router
│ ├── Validator.php ← Form doğrulama
│ ├── Console/Kernel.php ← CLI komutları
│ ├── Events/ ← Event sistemi
│ ├── Mail/ ← Mailable / Mailer
│ └── Middleware/ ← SecurityHeaders, VerifyCsrf
├── app/
│ ├── Controllers/
│ │ ├── Auth/ ← Login, Logout, Register
│ │ ├── Admin/ ← Post, Product, Category, Tag, Page, Seo, Language
│ │ ├── Front/ ← Post, Product, Page (public)
│ │ ├── AdminController.php ← İstatistik, izin, log
│ │ └── UserController.php
│ ├── Middleware/ ← Auth, Admin, Permission, Throttle, Locale, ApiAuth
│ ├── Models/ ← User, Post, Category, Tag, Product, Page, Language + Translations
│ └── Providers/ ← EventServiceProvider
├── config/ ← app, mail, cache, session, database
├── database/
│ ├── migrations/ ← 14+ migration
│ ├── seeders/ ← Users, Language, Category, Tag, Seo
│ └── factories/ ← UserFactory, PostFactory
├── routes/web.php
├── views/
│ ├── layouts/ ← admin/app.php, front.php, base.php
│ ├── auth/
│ ├── admin/ ← posts, products, categories, tags, pages, seo, languages
│ ├── front/ ← posts, products, pages
│ └── errors/ ← 403, 404, 500
├── tests/ ← 43 PHPUnit testi
├── stubs/ ← make:* şablonları
└── console ← CLI entry point
// Temel
Route::get('/about', 'PageController@about')->name('about');
Route::post('/contact', 'ContactController@store')->middleware('throttle:5,60');
// Grup + middleware
Route::prefix('/admin')->middleware('auth')->group(function () {
Route::get('/dashboard', 'DashboardController@index')->name('dashboard');
Route::get('/{id}/edit', 'UserController@edit')->name('admin.users.edit');
Route::put('/{id}', 'UserController@update')->name('admin.users.update');
Route::delete('/{id}', 'UserController@destroy')->name('admin.users.destroy');
});
// Resource CRUD (7 route tek satır)
Route::resource('users', 'UserController');
Route::apiResource('api/posts', 'Api\\PostController');
// Yardımcı
Route::view('/home', 'welcome', ['title' => 'Ana Sayfa']);
Route::redirect('/old', '/new', 301);
// Method spoofing (HTML form)
echo method_field('DELETE'); // <input type="hidden" name="_method" value="DELETE">namespace App\Controllers;
use Core\Request;
class PostController
{
// DI: Request otomatik inject edilir
public function store(Request $request)
{
$data = $request->only(['title', 'content']);
if ($request->hasFile('cover')) {
$path = \Core\FileUpload::upload($request->file('cover'), 'uploads/posts');
}
Post::create($data);
flash('success', 'Yazı oluşturuldu.');
redirect(route('admin.posts.index'));
}
}// app/Requests/StorePostRequest.php
class StorePostRequest extends \Core\FormRequest
{
public function rules(): array
{
return [
'title' => 'required|min:3|max:255',
'content' => 'required|min:10',
'email' => 'required|email|unique:users,email',
];
}
public function messages(): array
{
return ['title.required' => 'Başlık zorunludur.'];
}
}
// Controller — validation otomatik, başarısızsa back() + flash errors
public function store(StorePostRequest $request)
{
$data = $request->validated();
Post::create($data);
}Auth::check() // bool
Auth::user() // ?User (request başına tek DB sorgusu)
Auth::id() // ?int
Auth::attempt(['email' => $e, 'password' => $p, 'remember' => true])
Auth::login($user)
Auth::logout()
// API Token
[$plain, $token] = Auth::createToken($user, 'mobile', ['posts.read']);
Auth::loginWithToken($plainToken);
Auth::revokeTokens($user);// Aktif dil
Language::current() // 'tr', 'en', 'ru', 'fr'
Language::set('en') // Dil ayarla
Language::defaultSlug() // Varsayılan dil slug'ı
Language::all() // Tüm aktif diller
// URL üretimi
current_lang() // 'tr'
lang_url('/posts/slug', 'en') // '/en/posts/slug'
lang_switch_url('en') // Mevcut sayfanın İngilizce URL'i
front_route('posts.show', ['slug' => 'hello-world'])Route Pattern:
// Varsayılan dil (prefix yok)
Route::get('/posts/{slug}', 'Front\\PostController@show');
// Diğer diller
Route::prefix('/{lang}')->middleware('locale')->group(function () {
Route::get('/posts/{slug}', 'Front\\PostController@show');
});// Dispatch
event(new UserRegistered($user));
// Listener tanımı (app/Providers/EventServiceProvider.php)
protected array $listen = [
UserRegistered::class => [SendWelcomeEmail::class],
];
// Closure listener
Dispatcher::listen(UserRegistered::class, fn($e) => logger($e->user->id));
Dispatcher::once(OrderPlaced::class, fn($e) => notifyAdmin($e));// app/Mail/WelcomeMail.php
class WelcomeMail extends Mailable {
public function build(): static {
return $this->subject('Hoş Geldiniz!')
->view('emails/welcome', ['user' => $this->user]);
}
}
// Gönderim
Mail::to($user->email)->send(new WelcomeMail($user));
Mail::to('a@b.com')->cc('c@b.com')->send(new OrderMail($order));# Kod üretme
php console make:controller Admin/Report
php console make:model Comment
php console make:migration create_comments_table
php console make:middleware Role
php console make:request StorePost
php console make:mail Welcome
php console make:event OrderPlaced
php console make:listener SendInvoice
php console make:factory Comment
php console make:test UserAuth
# Veritabanı
php console migrate
php console migrate:rollback
php console migrate:fresh
php console db:seed
# Yardım
php console route:list
php console cache:clear
php console test
php console help| Koruma | Yöntem |
|---|---|
| CSRF | Session token, VerifyCsrfToken middleware |
| XSS | Plates e(), htmlspecialchars() |
| SQL Injection | Eloquent ORM, prepared statements |
| Open Redirect | Host whitelist (Redirect::to()) |
| Session Fixation | session_regenerate_id(true) login/logout'ta |
| Brute-force | IP + email bazlı rate limiting |
| MIME Spoofing | finfo ile gerçek MIME kontrolü |
| Path Traversal | basename() + regex (log viewer) |
| CSP | Nonce tabanlı, prod'da strict |
| Şifre | bcrypt (PASSWORD_DEFAULT) |
Muhammet Ali ŞAHİN
- GitHub: @malisahin89
Detaylı referans: FRAMEWORK.md | Proje geçmişi: PROJE_OZETI.md