I am trying to learn codeigniter in these days and I am struggling understanding the structure of views, controllers and models according to routes in order to maintain security.
So, how should we structure our views, controllers and models for admin backend and user backend, i mean folders, sub-folders and routing?
first I wanna mention how i am putting my files in order :
My route :
$route['default_controller'] = 'site/home';
$route['home'] = 'site/home';
so here a default controller is Site.php :
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Site extends CI_Controller {
/**
* Index Page for this controller.
*
* Maps to the following URL
* http://example.com/index.php/welcome
* - or -
* http://example.com/index.php/welcome/index
* - or -
* Since this controller is set as the default controller in
* config/routes.php, it's displayed at http://example.com/
*
* So any other public methods not prefixed with an underscore will
* map to /index.php/welcome/<method_name>
* #see https://codeigniter.com/user_guide/general/urls.html
*/
public function index()
{
$data['body']='site/home';
$this->load->view('includes/template',$data);
}
public function home(){
$data['body']='site/home';
$this->load->view('includes/template',$data);
}
public function AnotherMethod(){
$data['body']='site/AnotherPage';
$this->load->view('includes/template',$data);
}
And my view template is (views/includes/template.php) :
<?php
//load head
$this->load->view('includes/header');
//load body
$this->load->view($body);
//load footer
$this->load->view('includes/footer');
?>
So If i am putting things like this, I am having problem to accessing views from sub folders. As an example,
directory : views/site/userbackend/index.php
or views/site/adminbackend/index.php
And there are also controllers and models in sub folders according to the admin backend and user backend.
How i am going to access them?
I am here just trying to show what kind of problems i am having..
So now all the answers of the questions can be solved if you just direct me to the scenario how experts do and structure there components and what is the best practices.
I know i have made this question complex with many things at a time, i am sorry for that, if you want me to be clear more on one subject just tell me, i will update my question.
Need a helping hand here.
Thanks in Advance !
All views are available to all controllers, if:
View file exists
You specify the correct path to it
For views/site/userbackend/index.php should be $data['body'] = 'site/userbackend/index';
If my simple projects I have this structure:
controllers
backend
Admin.php
Admin_users.php
...
Main.php
News.php
...
views
backend
main
header.php
footer.php
users
view_list.php
view_form.php
frontend
main
header.php
footer.php
sidebar.php
news
view_list.php
view_item.php
mainpage.php
...
In view_list.php:
$this->load->view('frontend/main/header');
<news list>
$this->load->view('frontend/main/footer');
And I practice HMVC.
I had a similar issue and got it working for views in subfolders by adding .php to the view path, just like this:
$this->load->view('includes/template.php',$data);
Related
<?php
namespace Laravel\Horizon\Http\Controllers;
class HomeController extends Controller
{
/**
* Single page application catch-all route.
* #return \Illuminate\Http\Response
*/
public function index()
{
return view('horizon::app'); // what's the meaning of this 'horizon::app'
}
}
I found this syntax in the Laravel-Horizon Controller, can anyone explain this:
view('horizon::app');
What is the meaning of 'horizon::app'?
Like others answers stated, that is known as view namespaces. It not limited to the package's view, but you can use it inside your project as well.
As example you might have admin and customer module and want to differentiate their view by their own folder name, at this point you could use the namespace declaration. As example you might have these folders structures:
|- resources
|- views
|- admin
|- index.blade.php
|- customer
|- index.blade.php
Then you could register your own namespace that point to that particular folder path in AppServiceProvider.php:
app('view')->addNamespace('admin', base_path() . '/resources/views/admin');
// or
app('view')->addNamespace('customer', base_path() . '/resources/views/customer');
And later on, inside controller's method, you can reference it using:
return view("admin::index");
// or
return view("customer::index");
This syntax indicates that the View named app belongs to the horizon package. Think of it as package::view.path.
More info in Laravel's Package Development documentation.
To register your package's views with Laravel, you need to tell Laravel where the views are located.
Package views are referenced using the package::view syntax convention. So, once your view path is registered in a service provider, you may load the admin view from the courier package like so:
Route::get('admin', function () {
return view('courier::admin');
});
This feature used to be called view namespaces, if you've seen that term or want something else to search for. :)
:: is the scope (namespace) operator. Meaning app is declared within horizon.
Example (from php.net):
<?php
class MyClass {
const CONST_VALUE = 'Un valor constante';
}
$classname = 'MyClass';
echo $classname::CONST_VALUE; // A partir de PHP 5.3.0
echo MyClass::CONST_VALUE;
?>
Okay, so i have pages controller and user_authenticator controller.
pages controller is like a terminal to my views whilst the user_authenticator controller does the functions that relates to users like registration/logging in.
Whenever i'm done with a function in user_authenticator say for example logging in, how do i load the views via pages controller?
Login->user_auth(controller)->acc_model(model)->user_auth(controller)->view.
to
Login->user_auth->acc_model->pages(controller)->view.
It would be a boon for me if you guys can tell me if what i'm doing is impractical and a better way to do things. Or maybe i should just stick to loading views on the controller i used previously.
EDIT: so i may have forgotten the purpose of my pages controller but i remembered due to a moment of clarity from my foggy and tired mind.
I made a pages controller solely to load views, i guess in a sense, pages won't be loading ALL view but atleast most of the views, for example, if i had links in my views to other views, i would link them via the pages.
For specific functions that need specific controllers i guess i can let them handle loading some views.
Then again, if someone could tell me what i'm doing is a waste of time and should just delete pages controller please tell me so, i'd like to know why.
also if you have any suggestions for further uses of my pages controller thatd be great!
Also regarding session. I have a base controller.
<?php
class MY_Controller extends CI_Controller {
public function __construct()
{
parent::__construct();
}
public function is_logged_in($data){
$session = $this->session->userdata();
if($session['isloggedin']['username'] == ''){
return isset($session);
}else{
return FALSE;}
}
}
?>
How do i make it so that it automatically runs and checks for every controller i load if there are any session set?
Do i have to put it into a constructor? or do i have to call the base controller method from all controllers?
Here is the best solution for you.
You can use Hooks
Step1:
application/config/config.php
$config['enable_hooks'] = TRUE;//enable hook
Step2:
application/config/hooks.php
$is_logged_in= array();
$is_logged_in['class'] = '';
$is_logged_in['function'] = 'is_logged_in';//which function will be executed
$is_logged_in['filename'] = 'is_logged_in.php';//hook file name
$is_logged_in['filepath'] = 'hooks';//path.. default
$is_logged_in['params'] = array();
$hook['post_controller_constructor'][] = $is_logged_in;//here we decare a hook .
//the hook will be executed after CI_Controller construct.
//(also u can execute it at other time , see the CI document)
Step3:
application/hooks/is_logged_in.php //what u decared
<?php
//this function will be called after CI controller construct!
function is_logged_in(){
$ci =& get_instance();//here we get the CI super object
$session = $ci->session->userdata();//get session
if($session['isloggedin']){ //if is logged in = true
$ci->username = 'mike';//do what you want just like in controller.
//but use $ci instead of $this**
}else{
//if not loggedin .do anything you want
redirect('login');//go to login page.
}
}
Step4:application/controller/pages.php
<?php
class pages extends CI_Controller{
function construct ........
function index(){
echo $this->username;//it will output 'Mike', what u declared in hook
}
}
Hope it will help u.
In Laravel at the same time i need have different language/locale in site frontend and backend(administration). Frontend need 4 languages(en,de,fr,it), backend need 3 languages(en,lt,es).
Example: In browser i have two open tabs - 1 tab frontend (lang: de), 2 tab backend (lang: en). How to do it ? with setLocale? or i need different array for example backend?
One way you can easily handle this is by creating two BaseController classes for your frontend and backend controllers.
You can then set different languages for your frontend and backend from the right BaseController constructor using App::setLocale method.
Example:
<?php
class FrontendBaseController extends Controller
{
public function __construct()
{
App::setLocale(Session::get('frontend-locale'));
}
}
class BackendBaseController extends Controller
{
public function __construct()
{
App::setLocale(Session::get('backend-locale'));
}
}
class HomeController extends FrontendBaseController
{
public function __construct()
{
}
}
class BackendDashboardController extends BackendBaseController
{
public function __construct()
{
}
}
In the above example, I'm retrieving the current locale from the session.
You can put your language files in the app/lang folder. I will suggest you to have separate folders for your frontend and backend language files.
Example folder structure:
/app
/lang
/en
backend/
dashboard.php
frontend/
home.php
/de
backend/
dashboard.php
frontend/
home.php
Sample content of app/lang/en/backend/dashboard.php:
<?php
return array(
'welcome' => 'Welcome to Backend!'
);
You can output the value of welcome key for example with
echo Lang::get('backend/dashboard.welcome');.
I hope you got the idea. For more details, feel free to check out the official documentation.
Instead of opening two different tabs in the same browser, perhaps you should consider opening two different browser sessions, to avoid that the backend- and frontend-sessions with different language settings overwrite each other.
Let's take for example a small social network site. One of modules are also Quizzes. Quizzes module have the following sections:
-Create quize
-Edit quize
-Quize view
-Browse quizes
-Send quize to friend
I am wondering what would be the best way in this case. One of option is to create for each module section another controller.
controllers/create_quize.php
controllers/edit_quize.php
controllers/quize_view.php
controllers/browse_quizes.php
controllers/send_quize.php
Another way would be to create single controller for entire module with many functions. None of options are ok. In first way, this could mean to have more than 30 controllers in my controllers folder (having in mind that quizess is just one of many modules). Second option is not ok because a single file will have many functions and won't be easily scanned to developer.
I was also thinking to create many controllers, but organizing them into subfolders. Anyway condeigniter doesn't have this option without modification.
Tnx!
You only need a single controller for your quizzes. Your quiz controller might look like this :
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Quiz extends CI_Controller {
function __construct()
{
parent::__construct();
}
function index()
{
// Index page. List all quizzes here, perhaps as an replacement to /browse
// /quiz/
}
function create()
{
// Create a new quiz
// /quiz/create
}
function edit($quiz_id)
{
// Edit quiz with $quiz_id
// /quiz/edit/1
}
function browse()
{
// Index page. List all quizzes here, perhaps
// /quiz/browse
}
function send($quiz_id)
{
// Send/share page
// /quiz/send/1
}
}
CodeIgniter is a Model-view-controller framework. You may want to review how it's structured: http://codeigniter.com/user_guide/
I have a table of data from a database that I want to display on various pages of my website. Ideally, i would like to just have an include or something that will go off and get the data, and return the html table. The html and data will be identical everytime I need to use this.
I wanted to know the best way of doing this
Thanks
EDIT
If this helps, something similar to a Django "inclusion" custom tag...for any django developers reading
you need to pass the variable $data to the view method.
This is your code:
function load_my_view(){
$this->load->model('my_table');
$data['my_results'] = $this->my_table->my_data();
$this->load->view('my_view');
}
Please change it to this in order to load the $data into the view:
function load_my_view(){
$this->load->model('my_table');
$data['my_results'] = $this->my_table->my_data();
$this->load->view('my_view',$data);
}
You should use a function in a model to fetch the data you need. Your controller calls the model function and sends the returned information to a view. You don't need to use traditional php includes with Codeigniter. I recommend a review of the user guide. It's very good and will tell you all the basic stuff you need to know to develop with CI. But to get you started, you watn to use Models, Views, and Controllers. Your url will tell CI what controller and function inside that controller to run. If your url is
http://www.example.com/my_controller/load_my_view
Then CI will do what is inside the load_my_view function in the my_controller controller. function load_my_view in turn instantiates a model "my_table" and runs a database query, returns information that the controller sends to the view. A basic example follows:
Your model
class my_table extends CI_Model{
function my_data(){
$this->db->select('column_1,column_2,column_3');
$this->db->from('my_table');
$query = $this->db->get();
if($query->num_rows()>0){
$result = $query->result();
}
else{
$result = false;
}
return $result;
}
}
Your controller
class my_controller extends CI_Controller{
function load_my_view(){
$this->load->model('my_table');
$data['my_results'] = $this->my_table->my_data();
$this->load->view('my_view');
}
}
Your View
<ul id = "my_db_results">
<?php foreach($my_results as $result):?>
<li><?php echo $result->column_1." : ".$result->column_2." ( ".$result->column_3." )";?></li>
<?php endforeach;?>
</ul>
It looks like a good oportunity to use cache: http://codeigniter.com/user_guide/libraries/caching.html
Ok, so here is one thing that worked for me, but its definitely not perfect.
I created a view in which made a call to the model getting the data then put the data into a table. This way, I only have to include this view to put the table anywhere.
I understand this completely ruins the point of having a MVC framework, but hopefully it demonstrates what I want to do...and it works