URI Routing not working - php

I started working on a platform on CodeIgniter thanks to my work. The platform was started since before, so i just took the project. The thing is that i hadn't work with CI, so i just had a fast tutorial, and started developing based on how the platform was built. Now, to start, i decided to make a new page to to put a list of objects and understand a little how the PHP communicated with the HTML. The problem is that, when i go to the URL that i defined on routes.php, it gives an error "Requested resource does not exist", and i don't know what i'm doing wrong, while something similar works on other modules of the platform.
The files i'm using are:
list.php
// stuff
<?php if (has_access('agroindustrias')): ?>
<li class="<?php get_li_class('agroindustrias', $active); ?>" >
Agroindustrias
</li>
<?php endif ?>
// stuff
agroindustria.php
<?php
if (!defined('BASEPATH')) {
exit('No direct script access allowed');
}
class Agroindustria extends MY_Controller
{
public function __construct()
{
parent::__construct();
$this->load->model('agroindustria_model', 'agroindustria');
}
public function index($offset = 0)
{
$data['links'] = $this->paginate($this->agroindustria, 'agroindustrias', $offset);
$data['permisos'] = $this->getPermissions('usuario');
$data['active'] = 'usuarios';
$data['agroindustrias'] = $this->agroindustria->limit($this->limit, $offset)->get_all();
$data['submenu'] = $this->load->view('administracion/menu', $data, true);
$this->template->write_view('content', 'administracion/agroindustrias/list', $data);
$this->template->render();
}
}
routes.php(Updated with all the file, only the one before "reportes" doesn't work)
$route['administracion/agroindustria'] = 'agroindustria/index';
My URL is: http://localhost/work/administracion/agroindustria
The other controllers works with something similar, reason that i don't know what i'm doing wrong, if i still need to add something to another file, or if something that i wrote is wrong. Thanks in advance.

After the things that #Antony told me to check, i was able to find the error, it wasn't actually an error, just that the people before worked very much in the platform, that i did not undertand the mothodology to add new modules to the platform. All that i needed to do was register the new module, and the platform added the new URL as i wanted. Thanks Antony for your help!

1st of all rename agroindustria.php to Agroindustria.php if 1st letter not in upper case
if you are using method like this
public function index($offset = 0){
....
....
....
}
then you need to change routes like
$route['administracion/agroindustria/(:num)'] = 'agroindustria/index/$1';
and url
http://localhost/work/administracion/agroindustria/0
The best solution is change in your controller
//if offset not change
public function index(){
$offset = 0;
....
....
....
}
//if your offset depend upon 3rd segments of URL then
public function index(){
$offset = if($this->uri->segment(3)) ? $this->uri->segment(3) : 0;
....
....
....
}

Related

Including a file in CodeIgniter model is causing the server to dump the script on the web page

I'm trying to develop an application on code igniter framework. My question is when I wrote the model of my application it grew large, so I broke it down into two separate file. The main files merely calls the other one using include command.
The problem is that the calling file dumps the script in the called file in plain text on the web browser.
my model file looks like this :
<?php
defined('BASEPATH') or exit('No direct script access allowed');
class Admin_model extends CI_Model{
public function __construct(){
parent::__construct();
$this->load->database();
}
public function return_admin_dashboard_articles($priviledge_id,$by_author=null,$date_published=null){
$index = 0;
$query_articles = null;
//fetching list of articles
include 'includes/posts_query.inc.php';
return $data;
}
}
?>
and the file posts_query.inc.php looks like this:
<?php>
if($priviledge_id==1 || $priviledge_id==2){
$this->db->select('articles.id,articles.title,articles.summary,users.user_name,date(articles.pub_date) as
pubs_date,articles.author');//add date and time stamp to the table
$this->db->from('articles');
$this->db->join('users','articles.author=users.user_id');
if($by_author and $date_published==null){
$this->db->where('articles.author',$by_author);
}
else if($by_author=='all' and $date_published){
$this->db->where('date(articles.pub_date)=',$date_published);
}
$this->db->where('users.user_priviledge_id=',$priviledge_id); //change this to user_priviledge_id>$priviledge_id to see articles by all the users
$query_articles = $this->db->get();
}
//echo $query_articles;
else{
$this->db->select('articles.id,articles.title,articles.summary,users.user_name,date(articles.pub_date) as pubs_date,articles.author');//add date and time stamp to the table:done
$this->db->from('articles');
$this->db->join('users','articles.author=users.user_id');
$this->db->where('users.user_priviledge_id=',$priviledge_id);
$query_articles = $this->db->get();
}
if($query_articles->num_rows()>0){
foreach($query_articles->result_array() as $row){
$data['articles'][$index]=array(
'id'=>$row['id'],
'title'=>$row['title'],
'summary'=>$row['summary'],
'author'=>$row['user_name'],
'date'=>$row['pubs_date'],
'author_id'=>$row['author']
//'time'=>$row['time']
);
$index++;
}
}
else{
$data['error']['articles']='Could not fetch articles';
}
?>
The complete posts_query.inc.php file is displayed on the web page. What is the reason behind this? Any help will be much appreciated.
Thanks.
I'm running XAMPP (Apache 2.4.10, PHP 5.6.3,MySql 5.6 CodeIgniter 3.0) on windows 10.
The posts_query.inc.php file begins with <?php>.
It should be <?php. The > is causing the problem.

How To Use MVC PHP With Case Sensitive?

I am creating website in PHP. I am using MVC in PHP. My website works like this, if user go to example.com/about then it it will load About class and index() function. If user will go to localhost/about/founder then it will load founder() function from About class. but the thing is that if I go to localhost/About or localhost/AbOut or anything like that it is loading default index() function from About class file. So what to do with case sensitivity? I mean I want my script to load index() function from class file if it is localhost/about or localhost/terms. If anything is in uppercase, then it should load 404 error function. 404 error function is already set in my site.
Please help me friends.
here is my Bootstrap.php class file
<?php
/*
Bootstrap class to run functions by URL
*/
class Bootstrap {
public $_req;
public $_body;
public $_file;
public $_error;
function __construct(){
if(empty($_GET['req'])){
require 'classes/home.php';
$this->_body = new Home();
$this->hdr($this->_body->head());
$this->_body->index();
$this->ftr();
exit();
}
$this->_req = rtrim($_GET['req'], '/');
$this->_req = explode('/', $this->_req );
$_file = 'classes/'.$this->_req[0].'.php';
if(file_exists($_file)){
require $_file;
}
else {
$this->error(404);
}
$this->_body = new $this->_req[0];
$this->hdr($this->_body->head());
if(isset($this->_req[2])){
if(method_exists($this->_req[0], $this->_req[1])){
$this->_body->{$this->_req[1]}($this->_req[2]);
}else {
$this->error(404);
}
}else {
if(isset($this->_req[1])){
if(method_exists($this->_req[0], $this->_req[1])){
$this->_body->{$this->_req[1]}();
}else {
$this->error(404);
}
}else {
$this->_body->index();
}
$this->ftr();
}
}
//this function is to set header in html code
public function hdr($var = false){
echo '<!DOCTYPE HTML><html><head>'.$var.'</head><body>';
}
//this function is tp set footer in html code
public function ftr($var = false){
echo $var.'</body></html>';
}
//error handler
public function error($var){
require 'classes/er_pg.php';
$this->_error = new Error();
$this->_error->index($var);
}
}
You shouldn't use anything to load non-lowercase URLs because of the duplicate content, and that's a good thing you're doing. The wrong URLs should fail automatically in such cases.
However, since you didn't show how are you making those calls, then only thing I can suggest at this point is to check if the called method exists (case-sensitive), and if not, throw/redirect to a 404 page (header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found");).
UPDATE
After all the chat in the comments, seems like file_exists is not case-sensitive in your case, which is really weird. Hopefully someone will be able to figure it out so I can delete this (keeping it because of the info in the comments).
I solved the problem. I used this
if(ctype_lower($this->_req[0])){
$_file = 'classes/'.$this->_req[0].'.php';
and now its working. Thanx anyways friends.

Using Smarty 3.1 with Kohana 3.3

KSmarty is a Kohana module meant to integrate Smarty with Kohana. I'm trying to migrate my current project (already using Smarty) to using Kohana.
I'm trying to get KSmarty set up, but I'm having difficulties getting the templates to work. This is the "hello world" example from KSmarty:
application/classes/Controller/Welcome.php
<?php defined('SYSPATH') or die('No direct script access.');
class Controller_Welcome extends Controller_Template
{
public $template = 'welcome';
public function action_index()
{
// Assign a value to the variable 'intro'
$this->template->intro = 'Hello world!';
// Create a nested view by loading a different template
$this->template->content = View::factory('content');
}
}
// End Welcome
application/views/welcome.tpl
<html>
<body>
<h1>{$intro}</h1>
<p>
{$content}
</p>
</body>
</html>
application/views/content.tpl
Yes, this works!
However, for me, the controller/view combo does not work as expected. Here are the variants of action_index() that I've tried:
public function action_index()
{
echo 'foo';
}
// Output: foo
public function action_index()
{
// Assign a value to the variable 'intro'
$this->template->intro = 'Hello world!';
// Create a nested view by loading a different template
$this->template->content = View::factory('content');
}
// No output
// No error in apache log, php log, or kohana log
public function action_index()
{
Ksmarty::instance()->assign(array(
'intro' => 'Hello world!',
'content' => APPPATH.'/views/content.tpl'
// Note: also changed {$content} in template to {include $content}
));
Ksmarty::instance()->display(APPPATH.'/views/welcome.tpl');
}
// Expected HTML output
I could simply use Ksmarty::instance() like this and get my website working, but this isn't how the Kohana Views system was designed, and it feels like a kludge, especially since the KSmarty example matches up with Kohana's use of Views.
I'm pulling my hair out trying to pin this one down, which is impressive considering the amount of hair-pulling Kohana gave me on the initial install. What am I doing wrong?
Oh, I have make two changes to KSmarty to reach this point:
All instances of Kohana::config('smarty') replaced with Kohana::$config->load('smarty'); as far as I can tell, this is a matter of a version change in Kohana.
Commented out $s->security = Kohana::$config->load('smarty')->security;; as far as I can tell, this is a matter of a version change in Smarty, and KSmarty is configured to FALSE anyway.
Adding echo $this->template; to the end of the view works. It's not in the Kohana nor the KSmarty documentation/examples, but it's close enough to satisfy me. If anyone else ever comes up with an answer that solves the problem without echo, I'll mark that answer as accepted, but until that time, I have a solution.
<?php defined('SYSPATH') or die('No direct script access');
class Controller_Welcome extends Controller_Template
{
public $template = 'welcome';
public function action_index()
{
// Assign a value to the variable 'intro'
$this->template->intro = 'Hello world!';
// Create a nested view by loading a different template
$this->template->content = View::factory('content');
// Output the view
echo $this->template;
}
}
// End Welcome

Codeigniter Dynamic Routing

Hi i wont to make something like that.
http:// example.com/ - Main Controller
http:// example.com/rules/ - Main Controller where content get from database, but if not exist
return 404 page. (It's ok, isn't problem.)
But if i have subfolder in application/controlles/rules/
I want to redirect it to Main Contorller at Rules folder.
This follow code can solve problem, but i don't know how it right realise.
At routes.php:
$route['default_controller'] = "main";
$route['404_override'] = '';
$dirtest = $route['(:any)'];
if (is_dir(APPPATH.'controllers/'.$dirtest)) {
$route['(:any)'] = $dirtest.'/$1';
} else {
$route['(:any)'] = 'main/index/$1';
}
Ok, what I have:
controllers/main.php
class Main extends CI_Controller {
public function __construct()
{
parent::__construct();
$this->load->model('main_model');
}
public function index($method = null)
{
if (is_dir(APPPATH.'controllers/'.$method)) {
// Need re-rout to the application/controllers/$method/
} else {
if ($query = $this->main_model->get_content($method)) {
$data['content'] = $query[0]->text;
// it shows at views/main.php
} else {
show_404($method);
}
}
$data['main_content'] = 'main';
$this->load->view('includes/template', $data);
}
}
Updated Again (routes.php):
So, seem's like what i search (work example):
$route['default_controller'] = "main";
$route['404_override'] = '';
$subfolders = glob(APPPATH.'controllers/*', GLOB_ONLYDIR);
foreach ($subfolders as $folder) {
$folder = preg_replace('/application\/controllers\//', '', $folder);
$route[$folder] = $folder.'/main/index/';
$route[$folder.'/(:any)'] = $folder.'/main/$1';
}
$route['(:any)'] = 'main/index/$1';
But, in perfectly need some like this:
http:// example.com/1/2/3/4/5/6/...
Folder "controllers" has subfolder "1"?
YES: Folder "1" has subfolder "2"?
NO: Folder "1" has controller "2.php"?
NO: Controller "controllers/1/main.php" has function "2"?
YES: redirect to http:// example.com/1/2/ - where 3,4,5 - parameters..
It is realy nice, when you have structure like:
http://example.com/blog/ - recent blog's posts
http://example.com/blog/2007/ - recent from 2007 year blog's posts
http://example.com/blog/2007/06/ - same with month number
http://example.com/blog/2007/06/29/ - same with day number
http://example.com/blog/web-design/ - recent blog's post's about web design
http://example.com/blog/web-design/2007/ - blog' posts about web design from 2007 years.
http://example.com/blog/current-post-title/ - current post
Same interesting i find http://codeigniter.com/forums/viewthread/97024/#490613
I didn't thoroughly read your question, but this immediately caught my attention:
if (is_dir($path . '/' . $folder)) {
echo "$route['$folder/(:any)'] = '$folder/index/$1';"; //<---- why echo ???
}
Honestly I'm not sure why this didn't cause serious issues for you in addition to not working.
You don't want to echo the route here, that will just try to print the string to screen, it's not even interpreted as PHP this way. There are also some issues with quotes that need to be remedied so the variables can be read as variables, not strings. Try this instead:
if (is_dir($path . '/' . $folder)) {
$route[$folder.'/(:any)'] = $folder.'/index/$1';
}
Aside: I'd like to offer some additional resources that are not directly related to your problem, but should help you nonetheless with a solution:
Preferred way to remap calls to controllers: http://codeigniter.com/user_guide/general/controllers.html#remapping
Easier way to scan directories: http://php.net/manual/en/function.glob.php
It's hard to say why the registering of your routes fails. From your code I can see that you're not registering the routes (you just echo them), additionally I see that the usage of variables in strings are used inconsistently. Probably you mixed this a bit, the codeigniter documentation about routes is not precise on it either (in some minor points, their code examples are not really syntactically correct, but overall it's good).
I suggest you first move the logic to register your dynamic routes into a function of it's own. This will keep things a bit more modular and you can more easily change things and you don't pollute the global namespace with variables.
Based on this, I've refactored your code a bit. It does not mean that this works (not tested), however it might make things more clear when you read it:
function register_dynamic_routes($path, array &$route)
{
$nodes = scandir($path);
if (false === $nodes)
{
throw new InvalidArgumentException(sprintf('Path parameter invalid. scandir("$path") failed.', $path));
}
foreach ($nodes as $node)
{
if ($node === '.' or $node === '..')
continue
;
if (!is_dir("{$path}/{$node}")
continue
;
$routeDef = "{$folder}/(:any)";
$routeResolve = "{$folder}/index/\$1";
$route[$routeDef] = $routeResolve;
# FIXME debug output
echo "\$route['{$routeDef}'] = '{$routeResolve}';";
}
}
$path = APPPATH.'controllers/';
register_dynamic_routes($path, $route);
$route['(:any)'] = 'main/index/$1';
Next to this you probably might not want to shift everything onto the index action, but a dynamic action instead. Furthermore, you might want to have a base controller that is delegating everything into the sub-controllers instead of adding the routes per controller. But that's up to you. The example above is based on the directory approach you outlined in your question.
Edit: Additional information is available in the Controllers section next to the URI Routing section
All this seems kind of complicated.
Plus, if you have hundreds (or thousands or more?) of possible routes in a database you may not want to load all of them into the "$routes" array every time any page loads in your application.
Instead, why not just do this?
last line of routes.php:
$route['404_override'] = 'vanity';
Controller file: Vanity.php:
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Vanity extends MY_Controller {
/**
* Vanity Page controller.
*
*/
public function __construct() {
parent::__construct();
}
public function index()
{
$url = $_SERVER['PHP_SELF'];
$url = str_replace("/index.php/", "", $url);
// you could check here if $url is valid. If not, then load 404 via:
//
// show_404();
//
// or, if it is valid then load the appropriate view, redirect, or
// whatever else it is you needed to do!
echo "Hello from page " . $url;
exit;
}
}
?>

CakePHP - How do i set the page title to an item name?

OK, so I'm trying to teach myself the CakePHP framework, and I'm trying to knock up a simple demo app for myself.
I have the controllers, views and models all set up and working, but I want to do something slightly more than the basic online help shows.
I have a guitars_controller.php file as follows...
<?php
class GuitarsController extends AppController {
var $name = 'Guitars';
function index() {
$this->set('Guitars', $this->Guitar->findAll());
$this->pageTitle = "All Guitars";
}
function view($id = null) {
$this->Guitar->id = $id;
$this->set('guitar', $this->Guitar->read());
// Want to set the title here.
}
}
?>
The 'Guitar' object contains an attribute called 'Name', and I'd like to be able to set that as the pageTitle for the individual page views.
Can anyone point out how I'd do that, please?
NB: I know that there is general disagreement about where in the application to set this kind of data, but to me, it is data related.
These actions are model agnostic so can be put in your app/app_controller.php file
<?php
class AppController extends Controller {
function index() {
$this->set(Inflector::variable($this->name), $this->{$this->modelClass}->findAll());
$this->pageTitle = 'All '.Inflector::humanize($this->name);
}
function view($id = null) {
$data = $this->{$this->modelClass}->findById($id);
$this->set(Inflector::variable($this->modelClass), $data);
$this->pageTitle = $data[$this->modelClass][$this->{$this->modelClass}->displayField];
}
}
?>
Pointing your browser to /guitars will invoke your guitars controller index action, which doesn't exist so the one in AppController (which GuitarsController inherits from) will be run. Same for the view action. This will also work for your DrumsController, KeyboardsController etc etc.
You can set this in the controller:
function view($id = null) {
$guitar = $this->Guitar->read(null, $id);
$this->set('guitar', $guitar);
$this->pageTitle = $guitar['Guitar']['name'];
}
Or in the view:
<? $this->pageTitle = $guitar['Guitar']['name']; ?>
The value set in the view will override any value that may have already been set in the controller.
For security, you must ensure that your layout / view that displays the pageTitle html-encodes this arbitrary data to avoid injection attacks and broken html
<?php echo h( $title_for_layout ); ?>
In response to your own answer about oo paradigm. Its like this :
function view($id) {
$this->Guitar->id = $id;
$this->Guitar->read();
$this->pageTitle = $this->Guitar->data['Guitar']['name'];
$this->set('data', $this->Guitar->data);
}
By the way, you should check if id is set and valid etc, since this is url user input.
As of CakePHP 1.3, setting page title has been changed.
$this->pageTitle = "Title"; //deprecated
$this->set("title_for_layout",Inflector::humanize($this->name)); // new way of setting title
Note: More about Inflector: http://api13.cakephp.org/class/inflector#method-Inflector
$this->pageTitle = $this->Guitar->Name;
It should go in the View though, I don't PHP, or cakePHP, but thats something a view should do, not the controller.
It should go in the controller. See this
"but I want to do something slightly more than the basic online help shows."
Isn't that always the rub? So much documentation is geared towards a bare minimum that it really does not help much. You can complete many of the tutorials available but as soon as you take 1 step off the reservation the confusion sets in. Well, it's either bare minimum or pro developer maximum but rarely hits that sweet spot of ease, clarity and depth.
I'm currently rewriting some Zend Framework documentation for my own use simply so I can smooth out the inconsistencies, clarify glossed over assumptions and get at the core, "best practice" way of understanding it. My mantra: Ease, clarity, depth. Ease, clarity, depth.
Ah, the none-obvious answer is as follows...
$this->pageTitle = $this->viewVars['guitar']['Guitar']['Name'];
I found this by placing the following code in the controller (was a long shot that paid off, to be honest)
echo "<pre>"; print_r($this);echo "</pre>";
Thanks to all those that tried to help.
echo "<pre>"; print_r($this);echo "</pre>";
how about
pr( $this );
OK, I really want to set the page title in the controller instead in the view. So here's what I did:
class CustomersController extends AppController {
var $name = 'Customers';
function beforeFilter() {
parent::beforeFilter();
$this->set('menu',$this->name);
switch ($this->action) {
case 'index':
$this->title = 'List Customer';
break;
case 'view':
$this->title = 'View Customer';
break;
case 'edit':
$this->title = 'Edit Customer';
break;
case 'add':
$this->title = 'Add New Customer';
break;
default:
$title = 'Welcome to '.$name;
break;
}
$this->set('title',$this->title);
}
The trick is that you can't set $this->title inside any action, it won't work. It seems to me that the web page reaches action after rendering, however you can do it in beforeFilter.

Categories