Routing independant controllers and models in fat free framework - php

I am trying to create Main site navigation, Sidebar Navigation and Footer navigation in Fat Free environment. I am just starting to work with frameworks especially with MVC type.
My problem, since my navigation will be almost on every page of the website, I was thinking about creating separate controller and model to handle all this staff, but not sure how it would work without making routing?
Also, I am not sure how to handle join in the model, I could not find any information about this online at all.
Here is my current Category Controller
class Categories extends DB\SQL\Mapper
{
public function __construct(DB\SQL $db)
{
parent::__construct($db, 'categories');
}
public function all()
{
$this->load();
return $this->query;
}
public function getByID($id)
{
$this->load(array('id=?', $id));
return $this->query;
}
public function getBySlug($category_slug)
{
$this->load(array('category_slug=?', $category_slug));
return $this->query;
}
public function add()
{
$this->copyfrom('POST');
$this->save();
}
public function edit($id)
{
$this->load(array('id=?', $id));
$this->copyfrom('POST');
$this->update();
}
public function delete($id)
{
$this->load(array('id=?', $id));
$this->erase();
}
}
any ideas or pointers will help me to go a long way.
Thanks in advance

I don't know if understood what your issue is, but if you want to make the categories available for all methods in a Controller, you could use the beforeRoute() method:
class TestController extends MainController {
// runs before routing
// if another controller extends TestController and also has a
// beforeRoute, this will be overriden
function beforeRoute() {
// Load Categories
$categories = new Categories($this->db);
// Assiging ->all() to variable makes the method return an array of all results
$categoriesArray = $categories->all();
// Set an array in the hive for template use
$this->f3->set('categories', $categoriesArray );
// Clear the instance
$categories->reset();
}
function renderPage() {
// the 'categories' hive variable is available because beforeRoute has been run
// Set the page title from the dictionary file
$this->f3->set('pageTitle', $this->f3->get('DICT_'.'page_whatever') );
// Render the View
$this->f3->set('view','page.whatever.htm');
$template=\Template::instance();
echo $template->render('layout.sidebar.htm');
}
// End of Controller
}
And of course, in the template:
<repeat group="#categories" value="#category">
<li>
{{ #category.label }}
</li>
</repeat>
ps: You might be using $f3 instead of $this->f3 (and the same for $db)

Related

PHP - MVC, is my aproach correct?

So I have Model, View and Controller, my code works but i have no one to educate me if I do work with it properly.
I won't copy paste the whole code, so therefor I've drawed how it works:
THE PICTURE: MVC
The part of code:
class Site {
protected $config;
function __construct() {
$this->config = include("resources/config.php");
}
private function connect() { /*database connection*/ }
public function getData($var) {
/* connecting, $var = amout of rows, and storing the data in array() */
}
}
class SiteView {
private $data;
function __construct(Site $data) {
$this->model = $data;
}
public function output() {
if(!empty($this->model->data)) { /* displays the data */ }
}
public function render($template) {
return include("$template");
}
}
class SiteController {
public function __construct(Site $respond) {
$this->model = $respond;
}
public function condition() {
$view = new SiteView($this->model);
$view->render("header.php");
if(!isset($_GET['action'])) {
$view->render("body.php");
} else if($_GET['action'] === "report" AND isset($_GET['id'])) {
$view->render("report_body.php");
} else if ...
}
So the model and view is used in templates, and I'm not sure if it is a good thing or bad. Thanks for any kind of help or showing me the way.
The MVC or Model, View and Controller approach is Model is for data which used by user, Controller is the backend logic and View is the output in HTML or the User Interface (UI).
Normally every request come to the controller first. Controller is connected with the Model and View. Controller collect the data according to the request from Model and send the data to the View for show. View can not able to connect with model.
For more details see this link, Click Here

How to Use Cache and Keep code DRY in Laravel 5

I have the following lines of code that are being repeated, not only in many methods of a Controller but also in more than one Controller.
$Categories = \Cache::rememberForever('Categories', function() {
return \App\Models\Skill\Category_Model::all();
});
Is there any useful way that I can use this, such that the repeated code can be removed?
Use a Repository to access the Category_Model model:
//REPOSITORY CLASS
class CategoryRepository
{
public function getAll()
{
return \Cache::rememberForever('Categories', function() {
return \App\Models\Skill\Category_Model::all();
});
}
}
In the controllers where you need to get the categories, inject the repository from the controller's constructor, and access the repository from the methods:
//INJECT THE REPOSITORY IN YOU CONTROLLER'S CONSTRUCTOR
public function __construct( CategoryRepository $catRepo )
{
$this->catRepo = $catRepo;
}
public function index()
{
//get the categories from the repository
$categories = $this->catRepo->getAll();
}
This will keep your code DRY, as you only need to call $this->catRepo->getAll(); to get all the categories

PHP OOP-based login system

Lets say I am building an OOP-based user authentication system, and I would like to incorporate the following principles: Direct Injection, Inheritance, Encapsulation, Polymorphism and the Single Responsibility Principle.
My background in programming is has always relied on procedural programming, and thus, am finding it difficult to really put these practices into correct use.
Assume I have these classes:
class Config
{
public function set($key, $value);
public function get($key, $default = null);
}
class User
{
public function __construct(PDO $dbh, $id = null);
public function setProfile(Profile $profile);
}
class Auth
{
public function __construct(Config $config);
public function login($username, $password, $keepLoggedIn = true);
public function isLoggedIn();
public function getLoggedInUser();
public function logout();
public function register(array $data);
}
class Session
{
public function start($sessionName = null);
public function write($key, $value);
public function read($key, $default = null);
}
class Profile
{
public function setAddress(Address $address);
public function setName($name);
public function setDOB(DateTime $date);
public function getAge();
}
class Validator
{
public function validate($input);
}
I have intentionally left off the function bodies to keep things simple.
To the best of my knowledge, I believe I'm using the principles correctly. However, I am still unclear as to how you would connect classes like: the Validator to the User model, the User model to the Auth and the Session to the Auth class. All of which depend on each other.
You are on the right track. The way these classes connect to each other is called extending. I tend to go towards an MVC setup, meaning Model, View, Controller.
Your logic goes into the controller, all your DB queries and concrete back end methods go in the model. The controller receives requests and returns responses. It's the middleman. It talks to the back end after a request has been made to it, and feeds the front in via response.
So you have a core controller (keep it bare minimal), then each class you make extends the core controller. So your controller is where you tie all this together.
<?php
//your main core controller, where you load all these things you need avilable, so long as this class is extended
class CoreController {
public $auth
public $session;
public $view;
function construct__ ()
{
$this->auth = instantiateAuthClassHere();
$this->session = instantiateSessionClassHere();
$this->view = instantiateViewClassHere();
}
public function anotherHelperForSomething(){
//helper stuff for this method
}
}
//index, page, or content controller, depending on how many you need, i.e. if you want a controller for each page, thats fine, e.g indexController, etc..
//this is the middle man, has logic, receives requst, returns response to view.
class Controller extends CoreController {
public function index (){
$userModel = new userModel();
//do something with this
$session = $this->session;
$content = 'some html';
$userInfo = $userModel->getUsers();
$view = $this->view->render( array(
'content' => $content,
'userInfo' => $userInfo,
));
return $view;
}
}
//Core LIbraries
class Validator {
//your validator stuff
}
//Core LIbraries
class Session {
//your validator stuff
}
//Core LIbraries
class Auth {
//your validator stuff
}
class CoreModel{
public $validator;
function __construct(){
$this->validator = instantiateValidatorClassHere();
}
}
//a user model class (back end). you want a model class for each db table pretty much.
class UserModel extends CoreModel {
// if you need the validator anywhere inside this class, its globally available here inside any class that extends the CoreModel, e.g. $this->validator->methodName()
public function getUsers (){
$sql = 'SELECT * from users';
$result = $db->get($sql);
return $result;
}
}
Notice, on the Controller, this is a generic name for something like indexController, or anything custom. Also, I have the word extends there. It inherits all the objects from the parent that it extends. Inside it, now they will be available via $this->. See my example where I get $this->session.
Try to avoid constructs - you probably don't need them anywhere except for the core, and under special circumstances, which you might then need to check for yourself before you do even that. I dont use constructs much anymore. It can be a bit clunky and unmanageable.

Laravel: is it possible to set a controller dynamically for a route?

So, lets say I do have a simple Controller that handles Books.
App\Http\Controllers\SimpleBooksController
Inside routes.php I register a route for it:
Route::get('books/{id}','SimpleBooksController#doSimpleStuff');
But the world of books is not so simple. So I would like to have another Controller that handles the really complex book stuff.
In my head I imagine that something like this would be really useful:
class ComplexBooksController extends SimpleBooksController
So that routes that are not explicitly handled by the child class fall back to the parent class.
Now let's say each book knows if it is complex or not: $book->isComplex
And what I would like to do would be something like this
if (!$book->isComplex) {
// route 'books/{id}' to SimpleBooksController#doSimpleStuff
} else {
// route 'books/{id}' to ComplexBooksController#doComplexStuff
}
So, how could one accomplish this?
* edit *
The way I am currently handling this, is by setting the Controllers in routes.php statically, but let them listen to parameterized routes:
Route::get('books/simple/{id}', 'SimpleBooksController#doSimpleStuff');
Route::get('books/complex/{id}', 'ComplexBooksController#doComplexStuff');
According to the responses documentation, you should be able to use an anonymous function and return a redirect to the correct controller.
This assumes you have the data in a books table with isComplex:
Route::get('books/{id}', function($id) {
$result = DB::select('SELECT is_complex FROM books WHERE id = ?', [$id]);
if (empty($result)) abort(404);
$book = $result[0];
if ($book->is_complex)
return redirect()->action('SimpleBooksController#doSimpleStuff');
else
return redirect()->action('ComplexBooksController#doComplexStuff');
});
Your approaching this in the wrong way. You should not be trying to handle it with different controllers and routes.
A route for books should be the same - regardless of the book.
Your controller then makes a determination if the book is simple or complex - and calls the appropriate Command to handle this.
Route:
Route::get('books/{id}','BooksController#doSimpleStuff');
Controller:
class BooksController extends Controller
{
public function showBook($book)
{
if ($book->isComplex()) {
$this->dispatch(new HandleComplexBook($book));
} else {
$this->dispatch(new HandleSimpleBook($book));
}
}
}
Then you just have two commands - one for simple books, and one for complex books
class HandleComplexBook extends Command implements SelfHandling {
protected $book;
public function __construct(Book $book)
{
$this->book = $book;
}
public function handle()
{
// Handle the logic for a complex book here
}
}
class HandleSimpleBook extends Command implements SelfHandling {
protected $book;
public function __construct(Book $book)
{
$this->book = $book;
}
public function handle()
{
// Handle the logic for a simple book here
}
}

GET and POST functions in PHP / CodeIgniter

I like MVC (a lot), and I am trying to teach myself a framework of MVC architecture in all the major web languages of today.
I am currently on CodeIgniter and PHP. I searched online for a way to make the same function behave different for a POST and GET but couldn't find anything. Does CodeIgniter have this feature?
If you've used Ruby On Rails or ASP.NET MVC you'll know what I'm talking about, in them frameworks we can do this:
[GET]
public ActionResult Edit(int Id)
{
// logic here for GET
}
[POST]
public ActionResult Edit(EntityX EX)
{
// logic here for POST
}
I am so used to this, that I am finding it hard wrapping my head around how to get the same smooth functionality without that useful ability.
Am I missing something? How can I achieve the same thing in CodeIgniter?
Thanks
Am I missing something? How can I achieve the same thing in
CodeIgniter?
if you want to learn how to truly approach MVC in PHP, you can learn it from Tom Butler articles
CodeIgniter implements Model-View-Presenter pattern, not MVC (even if it says so). If you want to implement a truly MVC-like application, you're on the wrong track.
In MVP:
View can be a class or a html template. View should never be aware of a Model.
View should never contain business logic
A Presenter is just a glue between a View and the Model. Its also responsible for generating output.
Note: A model should never be singular class. Its a number of classes. I'll call it as "Model" just for demonstration.
So it looks like as:
class Presenter
{
public function __construct(Model $model, View $view)
{
$this->model = $model;
$this->view = $view;
}
public function indexAction()
{
$data = $this->model->fetchSomeData();
$this->view->setSomeData($data);
echo $this->view->render();
}
}
In MVC:
Views are not HTML templates, but classes which are responsible for presentation logic
A View has direct access to a Model
A Controller should not generate a response, but change model variables (i.e assign vars from $_GET or $_POST
A controller should not be aware of a view
For example,
class View
{
public function __construct(Model $model)
{
$this->model = $model;
}
public function render()
{
ob_start();
$vars = $this->model->fetchSomeStuff();
extract($vars);
require('/template.phtml');
return ob_get_clean();
}
}
class Controller
{
public function __construct(Model $model)
{
$this->model = $model;
}
public function indexAction()
{
$this->model->setVars($_POST); // or something like that
}
}
$model = new Model();
$view = new View($model);
$controller = new Controller($model);
$controller->indexAction();
echo $view->render();
The parameters only allow you to retrieve GET variables. If you want to get the POST variables, you need to use the Input library which is automatically loaded by CodeIgniter:
$this->input->post('data');
So, in your case, it would be:
public function edit($id = -1)
{
if($id >= 0 && is_numeric($id))
{
// logic here for GET using $id
}
else if($id === -1 && $this->input->post('id') !== false)
{
// logic here for POST using $this->input->post('id')
}
}
Note that you can also use this library to obtain GET, COOKIE and SERVER variables:
$this->input->get('data');
$this->input->server('data');
$this->input->cookie('data');

Categories