I have the following code in my routes.php in a codeigniter project.
$route['news/(:any)'] = 'news/view/$1';
$route['news'] = 'news';
$route['(:any)'] = 'pages/view/$1';
$route['default_controller'] = 'pages/view';
$route['(:any)'] = 'login/view/$1';
$route['default_controller'] = 'login/view';
The following url takes me to the about page correctly (which is located here: views/pages/about.php)
http://localhost:1234/ciblog/index.php/pages/view/about
Also http://localhost:1234/ciblog/index.php/news takes me to the news page correctly which is located here: views/news/index.php
I would like, however, http://localhost:1234/ciblog/index.php/about to take me to the about page, and instead a 404 error is returned. To clarify, I don't want to have to type in the "pages/view" in the url, to get to the about page. And the same for the login page. I don't want to have to type in login/view ....to get to the login.php page.
I thought that this line code, arranged for this to be routed such that pages/view is bypassed (that is the views/pages directory) so that it goes straight to the about.php page, but clearly, I am missing some logic.
The controller for the Pages.php is as so:
<?php
class Pages extends CI_Controller{
public function view($page = 'home')
{
if ( ! file_exists(APPPATH.'views/pages/'.$page.'.php'))
{
// Whoops, we don't have a page for that!
show_404();
}
$data['title'] = ucfirst($page); // Capitalize the first letter
$this->load->view('templates/header', $data);
$this->load->view('pages/'.$page, $data);
$this->load->view('templates/footer', $data);
}
}
Can someone point out what I've done wrong, but also, as an accepted answer, explain how exactly the routing works in simple terms. If I wanted to simply create a new page, and create a route (url) that allowed me to access that page from the localhost/page (i.e directly) what is the best method to do so?
For reference, a screenshot of the directory structure can be seen on the left.
You have two conflicting routes (:any).
$route['news/(:any)'] = 'news/view/$1';
$route['news'] = 'news';
$route['login/(:any)'] = 'login/view/$1';
$route['login'] = 'login/view';
$route['(:any)'] = 'pages/view/$1';
$route['default_controller'] = 'pages/view';
During the bootstrap CI will look com $route array trying to find a match for the current request. If a match is found, it'll then use the corresponding value as controller/method.
Unless you planned to do this way, you don't need a "view" method on your controller.
You could do something like this:
class Pages extends CI_Controller{
public function index()
{
$data['title'] = "Home";
$this->load->view('templates/header', $data);
$this->load->view('pages/home', $data);
$this->load->view('templates/footer', $data);
}
public function about()
{
$data['title'] = "About";
$this->load->view('templates/header', $data);
$this->load->view('pages/about', $data);
$this->load->view('templates/footer', $data);
}
}
So your route could be:
$route['about'] = 'pages/about';
$route['home'] = 'pages/home';
$route['default_controller'] = 'pages/home';
It is more verbose, but is easy to understand.
Related
Needing help understanding codeigniter 3 behavior
I'm not understanding the controller behavior very well and I ask for help
class Simulado extends CI_Controller {
function __construct(){
parent::__construct();
$this->load->helper('url');
$this->load->helper('funcoes_helper');
$this->load->helper('file');
$this->load->library('session');
$this->load->library('controle_acesso');
$this->load->model('resumoapp_model', 'resumo');
$this->load->model('homeapp_model', 'homeapp');
$this->load->model('simulado_model', 'simulado');
//permissão para acessar app
$this->controle_acesso->acesso();
$this->output->enable_profiler(TRUE);
}
public function index() {
$dados = '0'//todas as materias;
$bdinsert = $this->simulado->set_bd($dados);
$this->load->view('prova',$dados)
}
public function materia () {
$dados = 1; //idamateria
$bdinsert = $this->simulado->set_bd($dados);
$this->load->view('prova',$dados)
}
}
model
public function set_bd ($dados) {
$data = [
'id_mat' = $dados
];
$this->db->insert('simulados', $data);
}
routes.php
$route['default_controller'] = 'home';
$route['404_override'] = 'my404';
$route['translate_uri_dashes'] = FALSE;
$route['app'] = "/app/home";
$route['site'] = "/home";
when accessed through the link http://localhost/escola/app/simulado, the system behaves in the desired way, it writes the value zero once in the database, for example.
accessing the url we have the method of the class, simulated, http://localhost/escola/app/simulado/materia/1/exatas-matematica calls the method in the correct way, but when writing to the database it writes the code of the matter.
I did a test and put the same code of the article method in the index and called the url, and it worked perfectly, writing only once the code of the article in the database.
I need to know why it is recording 3 times in the database when accessing the url is a method of the class and has parameters.
Just wondering if this is a good way to write ajax code to interact with Laravel routes?
Example my application's require to list all customer data and also list all country through ajax. I have 3 controller ApiController, CustomerController, CountryController.
So in my routes.php I have this routes
Route::get('api/v1/ajax/json/{class}/{function}', 'Api\v1\ApiController#ajaxreturnjson');
In the ApiController.php, I have below function to call other controller function to return the data I need.
class ApiController extends Controller
{
public function ajaxreturnjson(Request $request, $controller, $function){
$input = $request->input();
if($request->input('namespace') != ''){
$namespace = $request->input('namespace');
unset($input['namespace']);
}else{
$namespace = 'App\Http\Controllers';
}
$data = array();
try {
$app = app();
$controller = $app->make($namespace.'\\'.$controller);
$data = $controller->callAction($function, array($request)+$input);
} catch(\ReflectionException $e){
$data['error'] = $e->getMessage();
}
return response()->json($data);
}
}
So example to use the ajax, I just need to pass the class name, namespace and also the function name to the ajax url.
Example to retrieve all customer info.
$.ajax({
dataType:"json",
url:"api/v1/ajax/json/CustomerController/getList",
data:"namespace=\\App\\Http\\Controllers\\",
success:function(data){
}
})
So in this way, I don't have to create so many routes for different ajax request.
But I am not sure if this will cause any security issue or is this a bad design?
Personally, I would not do it this way. Sure, you could do it this way, but it's not very semantic and debugging it could be a pain.
Also, if someone else begins working on the project, when they look at your routes file, they won't have any idea how your app is structured or where to go to find things.
I think it's better to have a controller for each Thing.
I am with CI a couple of days only. Previous experience - .NET C#.
My controller:
class Project extends CI_Controller {
public function __construct() { parent::__construct(); }
public function index() {
echo 'To be or not to be?';
}
}
The file name /application/config/controllers/Project.php
The routes.php:
$route['default_controller'] = 'home';
$route['project'] = 'project';
$route['404_override'] = '';
$route['translate_uri_dashes'] = FALSE;
The route for the default_controller works, no problem. $route['project'] returns 'Object not found', 404. The route's position in the list does not change anything. If I use http://my-site.com/index.php/project - this works fine.
Should I use .htaccess file? I did not think that it is an obligatory condition.
Where am I wrong?
Thank you in advance.
In application/config
Change:
$config['index_page'] = 'index.php';
to:
$config['index_page'] = '';
How can I link pages in my site considering routes.php?
Example:
$route['login'] = 'user/login';
The code above allows me to see "user/login" visiting just "login". But how can I link to that page using the internal route (user/login) and get as a result the "external route" "login".
I think it's important because I could change my URLs just modifiying "routes.php" and linking everything with internal routes.
From a Drupal perspective I can have my internal route "node/1" and the external url could be "about-us". So if I use "l('node/1')" this will return "about-us". Is there a function like "drupal_get_path_alias"?
Right now I can't find anything in the CI docs that point me to the right direction.
Thanks for your help.
You could have a look at using something like
http://osvaldas.info/smart-database-driven-routing-in-codeigniter
This would allow you to have the routes configured in the database. Then if you want to dynamically create you links through a model like this:
class AppRoutesModel extends CI_Model
{
public function getUrl($controller)
{
$this->db->select('slug');
$this->db->from('app_routes');
$this->db->where('controller', $controller);
$query = $this->db->result();
$data = $query->row();
$this->load->library('url');
return base_url($data->slug);
}
public function getController($slug)
{
$this->db->select('controller');
$this->db->from('app_routes');
$this->db->where('slug', $slug);
$query = $this->db->result();
$data = $query->row();
return $data->controller;
}
}
These have not been fully tested but will hopefully give you the general idea.
I hope this helps you :)
Edit------------------------------
You can create a routes_helper.php and add a function like
//application/helpers/routes_helper.php
function get_route($path)
{
require __DIR__ . '/../config/routes.php';
foreach ($route as $key => $controller) {
if ($path == $controller) {
return $key;
}
}
return false;
}
$this->load->helper('routes');
echo get_route('controller/method');
This does roughly what you want although this method does not support the $1 $2 etc vars that can be added to reflect the :num or :any wildcard that exist. You can edit the function to add that functionality but this will point you in the right direction :D
You can do that with .htaccess file:
Redirect 301 /user/login http://www.example.com/login
I'd like to ask why the following code works, redirects normally, and data is successfully inserted :
CategoriesController :
public function store()
{
$data = Input::all();
$category = new Term;
if($category->saveCategory($data)){
return Redirect::route('admin_posts_categories')->withSuccess('Category successfully added.');
}else{
return Redirect::route('admin_posts_categories')->withError('Failed to add category. #ErrorCode : 13');
}
}
Term model :
public function saveCategory($data){
$this->name = $data['name'];
$this->slug = $data['slug'];
if($this->save()){
$category_taxo = new TermTaxonomy;
$category_taxo->term_id = $this->lastCategoryId();
$category_taxo->taxonomy = 'category';
$category_taxo->description = $data['description'];
if($category_taxo->save()){
return true;
}else{
return false;
}
}else{
return "#Error Code : 4";
}
}
Where as the following only inserts the data but then shows a blank page and doesn't redirect :
CategoriesController :
public function store()
{
$data = Input::all();
$category = new Term;
$category->saveCategory($data);
}
Term Model
public function saveCategory($data){
$this->name = $data['name'];
$this->slug = $data['slug'];
if($this->save()){
$category_taxo = new TermTaxonomy;
$category_taxo->term_id = $this->lastCategoryId();
$category_taxo->taxonomy = 'category';
$category_taxo->description = $data['description'];
if($category_taxo->save()){
return redirect::route('admin_posts_categories')->withSuccess('Category successfully added.');
}else{
return redirect::route('admin_posts_categories')->withError('Failed to add category.');
}
}else{
return redirect::route('admin_posts_categories')->withError('#Error Code : 4.');
}
}
Moreover, I'd like to ask a few related questions, does my code conform to correct design patterns, and where should I put the redirect, in the model or in the controller ?
Try this for redirect:
1. return Redirect::back()->withSuccess('Category successfully added.');
OR
2. return Redirect::to(URL::to('admin_posts_categories'))->withSuccess('Category successfully added.');
Add your redirect login inside Controller. Even if you want to put in model (which is not recommended) use Ardent Hook function i.e. afterSave().
First of all never put redirect logic in model. Models are for putting business logic. Second thing check whether you have created route for admin_posts_categories in route.php or not and how you are calling views. If possible post your route code in question.
I recommend not putting redirects in your model. So the first solution would be the best of the two you have.
But back to your problem. It is showing a blank page because your store function is not returning anything. return $category->saveCategory($data); but as previously stated this method is not best practise.
An excellent tip would be to have a look at Laracasts, this will teach you everything you knew, didn't know and more about Laravel.