BG MVC sisteminde, app/controllers dizinindeki dosyalarda tanımlanmış controller sınıfından türetilmiş olan toplam 6 adet denetleyici sınıfı kullanılmaktadır.
BG MVC denetleyici sınıf tanımlamaları, app/controllers dizinindeki .php uzantılı dosyalarda yapılmaktadır.
İstek yapılan URL satırı hangi denetleyici ve hareket fonksiyonunu içerirse içersin, tüm işlemler aşağıda belirtilen sıra dahilinde gerçekleşir:
HomeController denetleyici sınıfı aşağıda gösterilen hareket fonksiyonlarından birisi ile çağrılır:
Controller sınıfından türetilen HomeController sınıf nesnesi yoluyla erişim sağlanan Controller sınıfı içindeki $view değişkeni yoluyla View sınıfı içindeki render() fonksiyonunu kullanarak ilgili görüntü dosyasını ve şablon dosyasını tarayıcıda gösterir.
C:\wamp\www\bgmvc\app\controllers\HomeController.php
<?php
namespace App\Controllers; // Namespace tanımı
use Core\{Controller, Router}; // Ana sınıf kullanımları
use App\Models\Articles; // Tablo model kullanımı
class HomeController extends Controller {
public function indexAction($pageno=''){
// Articles tablosundaki tüm sütunlar seçilerek kayıtlar id değeriyle büyükten küçüğe doğru sıralanır.
$params = [
'columns' => "*",
'order' => 'articles.id DESC'
];
// Articles tablosundaki toplam kayıt sayısı
$this->view->total = Articles::find_total($params);
// $params dizisine 'limit' ve 'offset' değerleri eklenir, $pageno değerine göre $page değeri belirlenir.
[$params, $page] = Articles::merge_with_pagination($params, $pageno, $this->view->total);
// Controller sınıfı $view nesnesi yoluyla limit ve page değişkenleri oluşturulur.
$this->view->limit = $params['limit'];
$this->view->page = $page;
// Articles tablosundaki tüm kayıt bilgileri articles adlı bir nesne dizisine aktarılır.
$this->view->articles = Articles::find($params);
// Web sayfası başlığını atama
$this->view->heading = "Son makaleler";
// Web sitesi başlığını atama
$this->view->set_site_title('Son makaleler');
// View sınıfı render() fonksiyonunu çağırma
$this->view->render();
}
public function detailsAction($id) {
// Articles tablosunda tüm sütunlar seçilerek kayıtlar id değerine sahip olan tek bir kayıt seçimi
$params = [
'columns' => "*",
'conditions' => "articles.id = :id",
'bind' => ['id' => $id]
];
// Bir POST değeri varsa (Makalenin detaylı görüntülendiği sayfadaki seçme kutusundan farklı bir makale seçilmiştir)
if($this->request->isPost()) {
// Javascript dosyasından okunan article_id değeri $params dizisinin 'bind' anahtarına atanır.
$params['bind']['id'] = $this->request->get('article_id');
// Articles tablosunda aranan kayıt bulunur ve $article değişkenine atanır.
$article = Articles::find_first($params);
// $article değeri json_encode() fonksiyonu ile json formatına dönüştürülerek ekrana yazılır.
echo(json_encode($article));
}
// Normal çalışma
else {
// Articles tablosunda aranan kayıt bulunur ve $article değişkenine atanır.
$article = Articles::find_first($params);
// Makale bulunamazsa, hata sayfasına yönlendirme
if(!$article) Router::redirect('exceptions/index/noarticle');
// View sınıfı yoluyla article değişkeni oluşturma
$this->view->article = $article;
// 'conditions' ve 'bind anahtarları silinir.
unset($params['conditions']);
unset($params['bind']);
// 'order' anahtarı, id sütun değeri büyükten küçüğe doğru sıralanacak şekilde, eklenir.
$params['order'] = 'articles.id DESC';
// Articles tablosundaki tüm kayıtlar $this->view->articles değişkenine atanır.
$this->view->articles = Articles::find($params);
// View sınıfı render() fonksiyonunu çağırma
$this->view->render();
}
}
}
indexAction fonksiyonu çağrıldıysa, sırayla aşağıdaki işlemler gerçekleştirilir:
include($full_path); // app/views/home/index.php
include($layout_path); // app/views/layout/default.php
detailsAction fonksiyonu çağrıldıysa, sırayla aşağıdaki işlemler gerçekleştirilir:
include($full_path); // app/views/home/details.php
include($layout_path); // app/views/layout/default.php
C:\wamp\www\bgmvc\app\views\home\index.php
<?php
use Core\{H, Config}; // Ana sınıf kullanımları
?>
<?php $this->start('content'); ?>
<?php
if(Config::get('main_slide')) {
$this->inc('inc/main_slide');
}
?>
<div class="p-3">
<nav class="navbar navbar-expand-lg bg-header">
<div class="container-fluid p-2">
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#MainNavbar" aria-controls="MainNavbar" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="MainNavbar">
<ul class="navbar-nav">
<li><?=$this->heading?></li>
</ul>
<ul class="navbar-nav ms-auto mb-2 mb-lg-0 bg-fontsm">
<?php // Sayfada gösterilecek kayıt sayısı seçimi ?>
<form class="mt-2" action="<?=ROOT?><?=H::get_action()?>" method="post">
<label class="me-2" for="records_limit">Kayıt sayısı</label>
<select name="records_limit" id="records_limit" class="custom-select">
<?php foreach([4, 6, 8, 10] as $limit) : ?>
<option
<?php if(isset($_SESSION['records_limit']) && $_SESSION['records_limit'] == $limit) echo 'selected'; ?>
value="<?= $limit; ?>">
<?= $limit; ?>
</option>
<?php endforeach; ?>
</select>
</form>
</ul>
</div>
</div>
</nav>
<?php // Makalelerin gösterimi ?>
<div class="row row-cols-1 row-cols-md-3 row-cols-lg-4 row-cols-xl-5 row-cols-xxl-6 g-4">
<?php foreach($this->articles as $article): ?>
<div class="col">
<div class="card h-100 shadow">
<div class="card-body">
<h5 class="card-title"><?= $article->title ?></h5>
<div class="bg-card-text mb-2"><?= html_entity_decode($article->body) ?></div>
<a href="<?=ROOT?>home/details/<?=$article->id?>" class="text-info">Detaylar</a>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
<?php // Sayfa yapısı oluşturma ?>
<?php $this->inc('inc/pager'); ?>
</div>
<?php $this->end(); ?>
index.php dosyasında sırayla aşağıdaki işlemler gerçekleştirilir:
C:\wamp\www\bgmvc\app\views\home\details.php
<?php $this->start('content'); ?>
<div class="m-3">
<select id="article_show" class="form-select form-select-sm mb-2 article_show" name="article_show" aria-label="Small select example">
<?php foreach($this->articles as $article): ?>
<option <?php echo ($article->id==$this->article->id) ? 'selected' : ''?> id="<?= $article->id ?>" class="" value="<?= $article->id ?>"><?= $article->title ?></option>
<?php endforeach; ?>
</select>
<div class="bg-white rounded border shadow-sm p-3">
<div class="row mb-4">
<div class="col flex-grow-1">
<h3 id="article_title"><?= html_entity_decode($this->article->title);?></h3>
</div>
</div>
<div id="article_body">
<?= html_entity_decode($this->article->body); ?>
</div>
</div>
</div>
<?php $this->end(); ?>
details.php dosyasında sırayla aşağıdaki işlemler gerçekleştirilir:
ActivitiesController denetleyici sınıfı aşağıda gösterilen hareket fonksiyonlarından birisi ile çağrılır:
Yukarıdaki erişim kısıtlamaları app/views/inc/acl.json dosyası ile veritabanı users tablosundan okunan acl sütun değerine göre yapılmaktadır. Bir kullanıcının erişim yetkisi olmadığında, menü seçeneği hiç gösterilmez.
Menüde gösterilmeden yapılan erişim kısıtlaması için acl.json dosyası, menüde gösterilerek yapılan erişim kısıtlaması için ise ilgili hareket fonksiyonu kullanılır.
C:\wamp\www\bgmvc\app\controllers\ActivitiesController.php
<?php
namespace App\Controllers;
use Core\{ Controller };
class ActivitiesController extends Controller {
public function softwareAction(){
$this->view->render();
}
public function codeAction(){
$this->view->render();
}
public function designAction(){
$this->view->render();
}
}
ActivitiesController denetleyici sınıfına gelen isteğin hareket fonksiyonuna karşılık gelen aşağıdaki görünüm dosyalarından birini görünüme dahil eder. Görünüm dosyaları:
C:\wamp\www\bgmvc\app\views\activities\software.php
<?php $this->set_site_title('Yazılım hizmetleri'); ?>
<?php $this->start('content'); ?>
<div class="row m-4">
<div class="text-center p-4 border rounded">
<h2 class="">Yazılım satış hizmetleri</h2>
<hr>
<img class="mx-auto mb-4 img-fluid rounded" src="<?=ROOT?>public/images/software.png">
<p>İşletim sistemleri, ofis programları, antivirüs programları ve kişiye özel özel paket program satışı.</p>
</div>
</div>
<?php $this->end(); ?>
C:\wamp\www\bgmvc\app\views\activities\code.php
<?php $this->set_site_title('Kodlama eğitimleri'); ?>
<?php $this->start('content'); ?>
<div class="row m-4">
<div class="text-center p-4 border rounded">
<h2 class="">Kodlama eğitimleri</h2>
<hr>
<img class="mx-auto mb-4 img-fluid rounded" src="<?=ROOT?>public/images/code.png">
<p>Programlama, web programlama ve tasarım faaliyetlerimizle hizmetinizdeyiz.</p>
<p>Programlama alanında C, C++, Gömülü programlama, MySQL, Windows API, Jva, Android, Python ve yapay zekada kullanımı konuları, web programlama alanında ise html, css, MVC, CMS ve Symfony Framework konuları işlenmektedir.</p>
</div>
</div>
<?php $this->end(); ?>
C:\wamp\www\bgmvc\app\views\activities\design.php
<?php $this->set_site_title('Web tasarım hizmetleri'); ?>
<?php $this->start('content'); ?>
<div class="row m-4">
<div class="text-center p-4 border rounded">
<h2 class="">Web tasarım hizmetleri</h2>
<hr>
<img class="mx-auto mb-4 img-fluid rounded" src="<?=ROOT?>public/images/design.png">
<p>Statik veya dinamik içeriğe sahip sıfırdan tasarlanmış veya hazır içerik yönetim sistemleriyle hazırlanmış web site kurulumu ve takibi.</p>
</div>
</div>
<?php $this->end(); ?>
CodesController denetleyici sınıfı indexAction hareket fonksiyonu ile çağrılır.
CodesController index.php dosyasına sadece, admin ve yetkilendirilmiş kullanıcılar erişim sağlayabilir (Users tablosu acl değeri admin veya authorized).
Menüde gösterilmeden yapılan erişim kısıtlaması için acl.json dosyası, menüde gösterilerek yapılan erişim kısıtlaması için ise ilgili hareket fonksiyonu kullanılır.
C:\wamp\www\bgmvc\app\controllers\CodesController.php
<?php
namespace App\Controllers;
use Core\{ Controller, Router };
use App\Models\Users;
class CodesController extends Controller {
public function indexAction() {
$user = Users::get_current_user();
// Kullanıcı kayıtlı ise
if($user) {
// Kullanıcı admin veya yetkili ise
if($user->acl=='admin' || $user->acl=='authorized') {
$this->view->render();
}
else {
Router::redirect('exceptions/index/noauthorized');
}
}
else {
Router::redirect('exceptions/index/nouser');
}
}
}
indexAction() fonksiyonu çağrıldığında, kullanıcı admin veya yetkili ise, index.php görünüm dosyasında aşağıdaki işlemler gerçekleştirilir:
C:\wamp\www\bgmvc\app\views\codes\index.php
<?php $this->set_site_title('Kod örnekleri'); ?>
<?php $this->start('content'); ?>
<div class="row m-4">
<div class="text-center p-4 border rounded">
<h2 class="">Kod örnekleri</h2>
<hr>
<img class="mx-auto mb-4 img-fluid rounded" src="<?=ROOT?>public/images/sample_codes.png">
<p>Bu sayfada yer alan örnek yazılım kodlarına sadece yetkilendirilmiş kullanıcılar erişim sağlayabilir.</p>
</div>
</div>
<?php $this->end(); ?>
AboutController denetleyici sınıfı indexAction hareket fonksiyonu ile çağrılır.
C:\wamp\www\bgmvc\app\views\about\index.php
<?php
namespace App\Controllers;
use Core\{ Controller};
class AboutController extends Controller {
public function indexAction(){
$this->view->render('about/index');
}
}
indexAction() fonksiyonu çağrıldığında, kullanıcı admin veya yetkili ise, index.php görünüm dosyasında aşağıdaki işlemler gerçekleştirilir:
C:\wamp\www\bgmvc\app\views\about\index.php
<?php $this->set_site_title('Hakkımızda'); ?>
<?php $this->start('content'); ?>
<div class="row m-4">
<div class="text-center p-4 border rounded">
<h2 class="">Hakkımızda</h2>
<hr>
<img class="mx-auto border rounded mb-4" src="<?=ROOT?>public/images/logo.png">
<p>BG MVC, MVC (Model View Controller - Model Görünüm Denetleyici) alt yapısı üzerine tasarlanmış, veri tabanı işlemlerini PDO (PHP Data Objects - PHP Veri Nesneleri) ile gerçekleştiren, PHP kodlama ile oluşturulmuş basit bir içerik sistemidir.</p>
<p>BG MVC kullanarak, bir web sitesinin alt yapısını oluşturabilirsiniz.</p>
</div>
</div>
<?php $this->end(); ?>
RegisterController denetleyici sınıfı aşağıda gösterilen hareket fonksiyonlarından birisi ile çağrılır:
C:\wamp\www\bgmvc\app\controllers\RegisterController.php
<?php
namespace App\Controllers; // Namespace tanımı
use Core\{Controller, Session, Router}; // Ana sınıf kullanımları
use App\Models\Users; // Tablo model kullanımı
class RegisterController extends Controller {
public function registerAction() {
$user = new Users(); // Yeni bir kullanıcı nesnesi oluşturma
// Form gönderilmiş ise
if($this->request->isPost()){
Session::csrf_check(); // Token kontrolü
// Users tablosundaki sütun değerlerinin adını içeren bir dizi oluşturma
$fields = ['fname', 'lname', 'email', 'acl', 'password', 'confirm'];
// $user nesnesine form değerlerini atama
foreach($fields as $field) {
// acl alanı ise 'user' değeri atama
if($field=='acl') {
$user->{$field} = 'user';
}
else {
$user->{$field} = $this->request->get($field);
}
}
// $user nesnesini users tablosuna kaydetme
if($user->save()) {
// Mesaj oluşturma
$msg = "Kullanıcı oluşturuldu";
Session::msg($msg, 'success');
// Giriş sayfasına yönlendirme
Router::redirect('register/login');
}
}
// $user nesne değerlerini görüntü dosyasına aktarma
$this->view->user = $user;
// Hataları görüntü dosyasına aktarma
$this->view->errors = $user->get_errors();
// register.php dosyasını çağırma
$this->view->render();
}
public function loginAction() {
$user = new Users(); // Yeni bir kullanıcı nesnesi oluşturma
$isError = true;
// Form gönderilmiş ise
if($this->request->isPost()) {
Session::csrf_check(); // Token kontrolü
// Form kullanıcı giriş değerlerini $users nesnesine aktarma
$user->email = $this->request->get('email');
$user->password = $this->request->get('password');
$user->remember = $this->request->get('remember');
// Users sınıfı ile giriş değerlerini doğrulama
$user->validate_login();
// $user nesnesi hatası yoksa
if(empty($user->get_errors())){
// Kullanıcı giriş değerleri ile Users sınıfı üzerinden Model sınıfı find_first() fonksiyonu ile kayıt alma
$u = Users::find_first([
'conditions' => "email = :email",
'bind' => ['email' => $this->request->get('email')]
]);
// Kayıt varsa
if($u) {
// Kullanıcının girdiği parola ile Users tablosundan okunan parolayı doğrulama
$verified = password_verify($this->request->get('password'), $u->password);
// Parolalar aynı ise
if($verified) {
$isError = false;
$remember = $this->request->get('remember') == 'on';
// Users sınıfı login() fonksiyonu ile bağlanma
$u->login($remember);
// Router sınıfı redirect() fonksiyonu ile login sayfasına erişim
Router::redirect('');
}
}
}
// Hata varsa
if($isError) {
$user->set_error('email', 'E-posta veya parola hatalı. Lütfen tekrar deneyin.');
$user->set_error('password', '');
}
}
// Hataları errors değişkenine atama
$this->view->errors = $user->get_errors();
// Kullanıcı nesnesini user değişkenine atama
$this->view->user = $user;
// login.php dosyasını çağırma
$this->view->render();
}
public function logoutAction() {
global $current_user;
if($current_user) {
// Kullanıcı giriş yapmış ise, çıkış yapma
$current_user->logout();
}
// Giriş sayfasına yönlendirme
Router::redirect('register/login');
}
}
registerAction fonksiyonu çağrıldıysa, sırayla aşağıdaki işlemler gerçekleştirilir:
include($full_path); // app/views/register/register.php
include($layout_path); // app/views/layout/default.php
loginAction fonksiyonu çağrıldıysa, sırayla aşağıdaki işlemler gerçekleştirilir:
include($full_path); // app/views/register/login.php
include($layout_path); // app/views/layout/default.php
logoutAction fonksiyonu çağrıldıysa, sırayla aşağıdaki işlemler gerçekleştirilir:
C:\wamp\www\bgmvc\app\views\register\register.php
<?php use Core\FH; ?>
<?php $this->start('content'); ?>
<div class="row m-4">
<div class="col-12 col-md-6 col-xl-4 bg-white rounded border shadow-sm p-4 mx-auto">
<h4 class="p-2 mb-2 bg-body-secondary rounded border border-primary-subtle text-center shadow-sm">Kayıt</h4>
<form action="" method="POST">
<?= FH::csrf_field();?>
<div class="row">
<?= FH::input_block('Adı', 'fname', $this->user->fname, ['class' => 'form-control'], ['class' => 'mb-36'], $this->errors); ?>
<?= FH::input_block('Soyadı', 'lname', $this->user->lname, ['class' => 'form-control'], ['class' => 'mb-3'], $this->errors); ?>
<?= FH::input_block('E-posta', 'email', $this->user->email, ['class' => 'form-control', 'type' => 'email'], ['class' => 'mb-3'], $this->errors); ?>
</div>
<div class="row">
<?= FH::input_block('Parola', 'password', '', ['class' => 'form-control', 'type' => 'password'], ['class' => 'mb-3'], $this->errors); ?>
<?= FH::input_block('Parola onayı', 'confirm', '', ['class' => 'form-control', 'type' => 'password'], ['class' => 'mb-3'], $this->errors); ?>
</div>
<div class="row">
<div class="col">
<a href="<?=ROOT?>register/login">Giriş yap</a>
</div>
</div>
<div class="text-end">
<a href="<?=ROOT?>register/register" class="btn btn-secondary">İptal et</a>
<input class="btn btn-primary" value="Kaydet" type="submit" />
</div>
</form>
</div>
</div>
<?php $this->end(); ?>
register.php görünüm dosyasında aşağıdaki işlemler gerçekleştirilir:
C:\wamp\www\bgmvc\app\views\register\login.php
<?php
use Core\FH;
use App\Models\Users;
?>
<?php $this->start('content');?>
<div class="row m-4">
<div class="col-12 col-md-6 col-xl-4 bg-white rounded border shadow-sm p-4 mx-auto">
<h4 class="p-2 mb-2 bg-body-secondary rounded border border-primary-subtle text-center shadow-sm">Giriş</h4>
<form method="POST">
<?= FH::csrf_field(); ?>
<div class="row">
<?= FH::input_block('E-posta', 'email', $this->user->email,['class' => 'form-control', 'type'=>'text'],['class' => 'mb-3 '], $this->errors); ?>
<?= FH::input_block('Parola', 'password', $this->user->password, ['class' => 'form-control', 'type' => 'password'], ['class' => 'mb-3'], $this->errors); ?>
</div>
<div class="row">
<div class="col">
<?= FH::check('Beni hatırla', 'remember', $this->user->remember == 'on', ['class' => 'form-check-input'], ['class' => 'mb-3 form-check'], $this->errors); ?>
<a href="<?=ROOT?>register/register">Kayıt ol</a>
</div>
</div>
<div class="text-end">
<a href="<?=ROOT?>register/login" class="btn btn-secondary">İptal et</a>
<input class="btn btn-primary" value="Giriş yap" type="submit" />
</div>
</form>
</div>
</div>
<?php $this->end(); ?>
ExceptionsController denetleyici sınıfı indexAction hareket fonksiyonu ile çağrılır.
C:\wamp\www\bgmvc\app\controllers\ExceptionsController.php
<?php
namespace App\Controllers;
use Core\Controller;
class ExceptionsController extends Controller {
public function indexAction($msg='noaccess') {
$msg_txt = '';
switch($msg) {
case 'nopage':
$msg_txt = 'Bu sayfa mevcut değil!';
break;
case 'noaccess':
$msg_txt = 'Bu sayfaya erişim yetkiniz yok!';
break;
case 'badtoken':
$msg_txt = 'Token değeriniz bozulmuş!';
break;
case 'noarticle':
$msg_txt = 'Makale mevcut değil!';
break;
case 'noauthorized':
$msg_txt = 'Bu sayfaya erişim özel yetki gerektirir!';
break;
case 'nouser':
$msg_txt = 'Kullanıcı kayıtlı değil!';
break;
case 'noview':
$msg_txt = 'Görünüm mevcut değil!';
break;
case 'notemplate':
$msg_txt = 'Şablon mevcut değil!';
break;
case 'nokey':
$msg_txt = 'Start metodu geçerli bir anahtar yok!';
break;
case 'nostart':
$msg_txt = 'Start metodu çalıştırılmamış!';
break;
}
$this->view->msg = $msg;
$this->view->msg_txt = $msg_txt;
$this->view->render('exceptions/index');
}
}
indexAction() fonksiyonunda aşağıdaki işlemler gerçekleştirilir:
include($full_path); // app/views/exceptions/index.php
include($layout_path); // app/views/layout/default.php
C:\wamp\www\bgmvc\app\views\exceptions\index.php
<?php $this->set_site_title('Giriş sınırlaması'); ?>
<?php $this->start('content'); ?>
<div class="row m-4">
<div class="col-12 col-lg-6 text-center p-4 border border-warning rounded mx-auto">
<h2 class="mb-4 p-2 rounded bg-secondary-subtle border border-secondary-subtle"><?=$this->msg_txt?></h2>
<div class="bg-exception mb-4">
<img class="" src="<?=ROOT?>public/images/<?=$this->msg?>.png">
</div>
<div>
<a href="<?=ROOT?>" class="btn btn-warning">Ana sayfa</a>
</div>
</div>
</div>
<?php $this->end(); ?>
index.php görünüm dosyasında aşağıdaki işlemler gerçekleştirilir: