How to use JRouter to rewrite controller and task URLs? - joomla

I'm using Joomla 1.5 with router.php file to rewrite URLs of views. Here are contents of router.php:
<?php
function PvcCalcProBuildRoute( &$query )
{
$segments = array();
if(isset($query['view']))
{
$segments[] = $query['view'];
unset( $query['view'] );
}
return $segments;
}
function PvcCalcProParseRoute( $segments )
{
$vars = array();
switch($segments[0])
{
case 'cart':
$vars['view'] = 'cart';
break;
case 'checkout':
$vars['view'] = 'checkout';
break;
case 'login':
$vars['view'] = 'login';
break;
case 'orders':
$vars['view'] = 'orders';
break;
case 'offers':
$vars['view'] = 'offers';
break;
}
return $vars;
}
?>
I need to enable URL rewriting for controller and task. For example this line:
JRoute::_('index.php?option=com_pvccalcpro&task=helpers');
I want to convert to /component/pvccalcpro/helpers.js
And this line:
JRoute::_('index.php?option=com_pvccalcpro&controller=orders&task=js');
I want to convert to /component/pvccalcpro/orders.js
I tried to figure out how to accomplish that with official Joomla Routing Manual, but after spending so many days it still didn't work out for me. Perhaps I'm missing something?
Here are contents of my orders controller for example:
<?php
// no direct access
defined('_JEXEC') or die();
jimport('joomla.application.component.model');
class PvcCalcProControllerOrders extends PvcCalcProController
{
function display()
{
parent::display();
}
function js()
{
$t=time()+31536000;
$expires = gmdate('D, d M Y H:i:s \G\M\T',$t);
header('Content-type: text/javascript; charset=utf-8');
header('Vary: Accept-Encoding');
header('Last-Modified: Tue, 27 Dec 2001 07:05:43 GMT');
header('Expires: '.$expires);
header('Cache-Control: public, max-age=31536000');
require_once(JPATH_COMPONENT.DS.'assets/js/orders.js');
die();
}
}
?>

In your two JRoute examples you're passing a path to your component but expecting it to return a path to your Javascript files.
JRoute is for creating human readable URLs for Joomla! components you are trying to use it for Javascript files by the looks of things.
To quote the Joomla! Doc's page - "Joomla can, initially, only create human readable URLs for built-in components."

Related

how to use jump to a specific div of current page in codeigniter

How do i convert this to codeigniter?
my php code for calling link is this
<ul>
<li>Register Here
<li>Login
</ul>
When I call this this specific link will be called.
<?php
#$opt = $_GET['option'];
if($opt=="") {
include('register.php');
error_reporting(1);
} else {
switch($opt) {
case 'register':
include('register.php');
break;
case 'login':
include('login.php');
break;
}
}
But I don't know how to do it in code igniter.
please help me
Try using a controller like Welcome.php or something
<?php
class Welcome extends CI_Controller {
public function index() {
// Load other data stuff.
// You should autoload the url helper.
$this->load->helper('url');
$opt = $this->input->get('option');
if($opt == "") {
$data['title'] = 'Register';
$this->load->view('header', $data);
$this->load->view('register');
$this->load->view('footer');
error_reporting(1);
} else {
switch($opt) {
case 'register':
$data['title'] = 'Register';
$this->load->view('header', $data);
$this->load->view('register');
$this->load->view('footer');
break;
case 'login':
$data['title'] = 'Login';
$this->load->view('header', $data);
$this->load->view('login');
$this->load->view('footer');
break;
}
}
}
Config.php
$config['base_url'] = 'http://localhost/yourproject/';
$config['index_page'] = 'index.php';
URI
$config['uri_protocol'] = 'REQUEST_URI';
To this
$config['uri_protocol'] = 'QUERY_STRING';
And then you can enable
$config['enable_query_strings'] = TRUE;
And use the built in codeigniter query strings.
Then you would use a link like
<li><?php echo anchor('c=welcome&option=register', 'Register');?></li>
The letter c mean controller in codeigniter query string but you can change that in config.php

Error 500 "View Not Found" when using SEF and URL Rewriting

I am writing a custom component. I have the view employees. Under this view, I have two layouts, default and modal.
I have a menu item in the toplevel of the main menu, Employees that points to my employee view:
index.php?option=com_mycomponent&view=employees which resolves to domain.com/joomla/employees and displayes the default view as expected.
Now, inside my component I want to link to the modal view, and I do so using JRoute and this url:
index.php?option=com_mycomponent&view=employees&layout=modal
Which resolves to
domain.com/joomla/employees/modal
And produces this error:
500 - View not found [name, type, prefix]: modal, html,
mycomponentView
If I visit index.php using index.php?option=com_mycomponent&view=employees&layout=modal my modal view is displayed.
I have also found that visiting domain.com/joomla/employees/employees/modal displays the correct layout. It is as if joomla is forgetting what view is associated with the menu item at /joomla/employees, and instead looks for the view "modal" unless the extra "employees" is provided in the url.
Also worth noting, domain.com/joomla/employee?layout=modal works fine as well.
Here is what I have for my router.php. This was file was generated for me using the component generator at j-cook.pro.
<?php
defined('_JEXEC') or die;
function MycomponentBuildRoute(&$query){
$segments = array();
if(isset($query['view']))
{
$view = $query['view'];
$segments[] = $view;
unset( $query['view'] );
}
if(isset($query['layout']))
{
$segments[] = $query['layout'];
unset( $query['layout'] );
}
if(isset($query['id']))
{
if(in_array($view, array('edit','view','view','editfacility','view','edit','client','editclient','viewposition','editposition','edit','view','edit','view','view','edit','view','edit','view','edit','view','edit')))
{
$segments[] = (is_array($query['id'])?implode(',', $query['id']):$query['id']);
unset( $query['id'] );
}
};
return $segments;
}
function MycomponentParseRoute($segments)
{
$vars = array();
$vars['view'] = $segments[0];
$nextPos = 1;
if (isset($segments[$nextPos]))
{
$vars['layout'] = $segments[$nextPos];
$nextPos++;
}
if(in_array($vars['view'], array('edit','view','view','editfacility','view','edit','client','editclient','viewposition','editposition','edit','view','edit','view','view','edit','view','edit','view','edit','view','edit'))
&& isset($segments[$nextPos]))
{
$slug = $segments[$nextPos];
$id = explode( ':', $slug );
$vars['id'] = (int) $id[0];
$nextPos++;
}
return $vars;
}
So it is hard to provide an exact answer for this without knowing all the different ways that you want to have urls be parsed. But I will try to give a hint at what will solve this present situation (without hopefully introducing too many new issues!)
The basic issue is that the BuildRoute side does not get a view value so it is not included in the url. On the one hand it is not necessary, because it is in the menu. But it makes it a little harder to parse, so option one is to force there to be a view if you can by changing the top function to start like this:
function MycomponentBuildRoute(&$query){
$segments = array();
if(isset($query['view']))
{
$view = $query['view'];
$segments[] = $view;
unset( $query['view'] );
}
else
{
$app = JFactory::getApplication();
$menu = $app->getMenu();
$active = $menu->getActive();
if ($view = $active->query['view']) {
$segments[] = $view;
}
}
...
In this way, if there is a menu item for this and it has a view we will tack it on. This should generate domain.com/joomla/employees/employees/modal.
You could also probably do this logic on the parse side too. This would go instead of the other option above:
function MycomponentParseRoute($segments)
{
$vars = array();
$app = JFactory::getApplication();
$menu = $app->getMenu();
$active = $menu->getActive();
if ($active->query['view']) {
$vars['layout'] = $segments[0];
$nextPos = 1;
} else {
$vars['view'] = $segments[0];
$nextPos = 1;
if (isset($segments[$nextPos]))
{
$vars['layout'] = $segments[$nextPos];
$nextPos++;
}
}
... continue with final check for id
I would probably use the second option but both are an option. By the way, you are also likely to run into issues if you try to use an id without setting a layout.

Redirect , POST and Flashdata issue in Codeigniter

i am developing an application where i need some suggestions. Here is the detail of the problem.
public function form()
{
$this->load->helper('inflector');
$id = $this->uri->segment(3,0);
if($data = $this->input->post()){
$result = $this->form_validation->run();
if($result){
if($id > 0){
// here update code
}else{
$this->mymodel->insert($data);
$this->session->set_flashdata('message','The page has been added successfully.');
$this->redirect = "mycontroller/index";
$this->view = FALSE;
}
}else{
//$this->call_post($data);
$this->session->set_flashdata('message','The Red fields are required');
$this->view = FALSE;
$this->redirect = "mycontroller/form/$id";
}
}else{
$row = $this->mymodel->fetch_row($id);
$this->data[]= $row;
}
}
public function _remap($method, $parameters)
{
if (method_exists($this, $method))
{
$return = call_user_func_array(array($this, $method),$parameters);
}else{
show_404();
}
if(strlen($this->view) > 0)
{
$this->template->build('default',array());
}else{
redirect($this->redirect);
}
}
Here you can see how i am trying to reload the page on failed validation.
Now the problem is that i have to display the flash data on the view form which is only available after redirect and i need to display the validation errors to which are not being displayed on redirect due to the loss of post variable. If i dont use redirect then cant display flashdata but only validation errors. I want both of the functionalities togather. I have tried even creating POSt again like this
public function call_post($data)
{
foreach($data as $key => $row){
$_POST[$key] = $row;
}
}
Which i commented out in the formmethod.How can i achieve this.
Here's a thought.
I think you can add the validation error messages into the flash data. Something like this should work:
$this->session->set_flashdata('validation_error_messages',validation_errors());
Notice the call to the validation_errors function. This is a bit unconventional, but I think it should work. Just make sure that the code are executed after the statement $this->form_validation->run(); to make sure the validation error messages are produced by the Form Validation library.
well i have little different approach hope will help you here it is
mycontroller extend CI_Controller{
function _remap($method,$params){
switch($method){
case 'form':
$this->form($params);
break;
default:
$this->index();
break;
}
}
function form(){
$this->load->helper('inflector');
$id = $this->uri->segment(3,0);
$this->form_validation->set_rules('name','Named','required|trim');
$this->form_validation->set_rules('email','email','required|valid_email|trim');
// if validation fails and also for first time form called
if(!$this->form_validation->run()){
$this->template->build('default',array());
}
else{ // validation passed
$this->save($id)
}
}
function save($id = 0){
$data = $this->input->post();
if($id == 0){
$this->mymodel->insert($data);
$this->session->set_flashdata('message','The page has been added successfully.');
$this->redirect = "mycontroller/index";
$this->view = FALSE;
}else{
// update the field
$this->session->set_flashdata('message','The Red fields are required');
}
redirect("mycontroller/index");
}
}
your form/default view should be like this
<?
if(validation_errors())
echo validation_errors();
elseif($this->session->flashdata('message'))
echo $this->session->flashdata('message');
echo form_open(uri_string());// post data to same url
echo form_input('name',set_value('name'));
echo form_input('email',set_value('email'));
echo form_submit('submit');
echo form_close();
try it if you face any problem post here.

precontroller hooks in codeigniter

I am using pre-controller hook codeigniter in my project
Description:
we are using subdomain concept and three templates(theme). eg: My site is xyz.com. this is having one first template.
some business signup with this xyz site. for eg. abc(business). We create abc.xyz.com. abc chooses 2 template. abc.xyz.com in browser need to show 2nd template. It is not showing 2nd template. it is showing only 1st template.
When we clicked any link on the site more than once , then the template 2 is set for abc.xyz.com link.
I am using codeigniter. loaded session, database in autoload files.
I used precontroller hook to check whether the url is xyz or any subdomain abc.xyz.com
In hook i am setting template if the url is subdomain one.
But template is not showing when abc.xyz.com is in browser. when i refresh the url for some clicks or clicked any of the header link some count , it showing the actual template of the business abc.
Please help me to fix this issue or provide me some solution .
<?php
class Subdomain_check extends CI_Controller{
public function __construct(){
parent::__construct();
$this->CI =& get_instance();
if (!isset($this->CI->session))
{
$this->CI->load->library('session');
}
}
function checking()
{
$subdomain_arr = explode('.', $_SERVER['HTTP_HOST']); //creates the various parts
if($subdomain_arr[0] == 'www')
{
$subdomain_name = $subdomain_arr[1]; //2ND Part
}
else
{
$subdomain_name = $subdomain_arr[0]; // FIRST Part
}
header ("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header ("Cache-Control: no-cache, must-revalidate");
header ("Pragma: no-cache");
if( $subdomain_name != 'xyz' )
{
$where = array();
$where['subdomain_name'] = $subdomain_name;
$where['status'] = 1;
$this->db->from('subdomain_map');
$this->db->where($where);
$query = $this->db->get();
if($query->num_rows() < 1)
{
header('Location:http://xyz.com/index.php?/error');
}
else
{
$result = $query->row_array();
$this->CI->session->set_userdata('subdomain_id',$result['subdomain_id']);
$this->CI->session->set_userdata('subdomain_name',$result['subdomain_name']);
$org_id = gat_organisationid_using_subdomainid($result['subdomain_id']);
$this->CI->session->set_userdata('organisation_id', $org_id);
if($org_id)
{
$templ_id = get_templid_using_organisationid($org_id);
$org_logo = get_organisation_logo($org_id);
}
if($templ_id){
if($this->session->userdata('pinlogin'))
$this->CI->session->set_userdata('template_set', 4);
else
$this->CI->session->set_userdata('template_set', $templ_id);
}
if($org_logo)
$this->CI->session->set_userdata('org_logo', $org_logo);
}
}
else
{
$this->CI->session->unset_userdata('subdomain_id');
$this->CI->session->unset_userdata('subdomain_name');
if( $this->CI->session->userdata('user_id') && $this->CI->session->userdata('user_category')<=2 )
{
$this->CI->session->unset_userdata('organisation_id');
$this->CI->session->unset_userdata('org_logo');
}
}
}
}
Here is the basic check you need to support custom themes per subdomain
// Gets the current subdomain
$url = 'http://' . $_SERVER['HTTP_HOST'];
$parsedUrl = parse_url($url);
$host = explode('.', $parsedUrl['host']);
// store $host[0], which will contain subdomain or sitename if no subdomain exists
$subdomain = $host[0];
// check for subdomain
if ($subdomain !== 'localhost' OR $subdomain !== 'mysite')
{
// there is a subdomain, lets check that its valid
// simplified get_where using activerecord
$query = $this->db->get_where('subdomain_map', array('subdomain_name' => $subdomain, 'status' => 1));
// num_rows will return 1 if there was a valid subdomain selected
$valid = $query->num_rows() === 1 ? true : false;
if($valid)
{
// set theme, user_data, etc. for subdomain.
}
else
{
// get user out of here with redirect
header('Location: http://' . $_SERVER['HTTP_HOST'] . '/error');
exit();
}
}
Note that when using subdomains with codeigniter, you should set your config > base_url to the following:
$config['base_url'] = 'http://' . $_SERVER['HTTP_HOST'] . '/poasty/poasty-starterkit/';
this will ensure things like site_url() and other CI helpers still work.
Reading through your code may I suggest utilizing more of Codeigniters built-in functionality, for example your __construct function has a lot of un-necessary code:
Original code
public function __construct(){
parent::__construct();
/**
* CI already exists
* since this controller extends CI_controller, there is already and instance of CI available as $this.
$this->CI =& get_instance();
*/
/**
* duplicate check, CI checks if library is loaded
* and will ignore if loaded already
if (!isset($this->CI->session))
{
$this->CI->load->library('session');
}
*/
$this->CI->load->library('session');
}
Optimized for Codeigniter
public function __construct()
{
parent::__construct();
$this->CI->load->library('session');
}
I suggest reading up on the Codeigniter user_guide to better understand what codeigniter can do. #see http://codeigniter.com/user_guide/
I hope you find this helpful!

Codeigniter - form validation doesn't work for files

i need to set a input file as required into my Codeigniter Controller.
This is my form_validation:
$this->form_validation->set_rules('copertina','Foto principale','required|xss_clean');
and this is the form:
<?php echo form_open_multipart('admin/canile/nuovo'); ?>
<li class="even">
<label for="copertina">Foto principale <span>*</span></label>
<div class="input"><input type="file" name="copertina" value="<?php echo set_value('copertina'); ?>" id="copertina" /></div>
</li>
<?php echo form_close(); ?>
But after the submit the form say that the file is not set, so the required clausole fails...how can i fix it?
File upload data is not stored in the $_POST array, so cannot be validated using CodeIgniter's form_validation library. File uploads are available to PHP using the $_FILES array.
It maybe possible to directly manipulate the $_POST array using data from the $_FILES array, before running form validation, but I haven't tested this. It's probably best to just check the upload library process for errors.
In addition, it is not possible, for security reasons, to (re-)set the value on page reload.
To make validation to work for files you have to check whether is it empty.
like,
if (empty($_FILES['photo']['name']))
{
$this->form_validation->set_rules('userfile', 'Document', 'required');
}
you can solve it by overriding the Run function of CI_Form_Validation
copy this function in a class which extends CI_Form_Validation .
This function will override the parent class function . Here i added only a extra check which can handle file also
/**
* Run the Validator
*
* This function does all the work.
*
* #access public
* #return bool
*/
function run($group = '') {
// Do we even have any data to process? Mm?
if (count($_POST) == 0) {
return FALSE;
}
// Does the _field_data array containing the validation rules exist?
// If not, we look to see if they were assigned via a config file
if (count($this->_field_data) == 0) {
// No validation rules? We're done...
if (count($this->_config_rules) == 0) {
return FALSE;
}
// Is there a validation rule for the particular URI being accessed?
$uri = ($group == '') ? trim($this->CI->uri->ruri_string(), '/') : $group;
if ($uri != '' AND isset($this->_config_rules[$uri])) {
$this->set_rules($this->_config_rules[$uri]);
} else {
$this->set_rules($this->_config_rules);
}
// We're we able to set the rules correctly?
if (count($this->_field_data) == 0) {
log_message('debug', "Unable to find validation rules");
return FALSE;
}
}
// Load the language file containing error messages
$this->CI->lang->load('form_validation');
// Cycle through the rules for each field, match the
// corresponding $_POST or $_FILES item and test for errors
foreach ($this->_field_data as $field => $row) {
// Fetch the data from the corresponding $_POST or $_FILES array and cache it in the _field_data array.
// Depending on whether the field name is an array or a string will determine where we get it from.
if ($row['is_array'] == TRUE) {
if (isset($_FILES[$field])) {
$this->_field_data[$field]['postdata'] = $this->_reduce_array($_FILES, $row['keys']);
} else {
$this->_field_data[$field]['postdata'] = $this->_reduce_array($_POST, $row['keys']);
}
} else {
if (isset($_POST[$field]) AND $_POST[$field] != "") {
$this->_field_data[$field]['postdata'] = $_POST[$field];
} else if (isset($_FILES[$field]) AND $_FILES[$field] != "") {
$this->_field_data[$field]['postdata'] = $_FILES[$field];
}
}
$this->_execute($row, explode('|', $row['rules']), $this->_field_data[$field]['postdata']);
}
// Did we end up with any errors?
$total_errors = count($this->_error_array);
if ($total_errors > 0) {
$this->_safe_form_data = TRUE;
}
// Now we need to re-set the POST data with the new, processed data
$this->_reset_post_array();
// No errors, validation passes!
if ($total_errors == 0) {
return TRUE;
}
// Validation fails
return FALSE;
}
Have you looked at this ->
http://codeigniter.com/user_guide/libraries/file_uploading.html
<?php
class Upload extends CI_Controller {
function __construct()
{
parent::__construct();
$this->load->helper(array('form', 'url'));
}
function index()
{
$this->load->view('upload_form', array('error' => ' ' ));
}
function do_upload()
{
$config['upload_path'] = './uploads/';
$config['allowed_types'] = 'gif|jpg|png';
$config['max_size'] = '100';
$config['max_width'] = '1024';
$config['max_height'] = '768';
$this->load->library('upload', $config);
if ( ! $this->upload->do_upload())
{
$error = array('error' => $this->upload->display_errors());
$this->load->view('upload_form', $error);
}
else
{
$data = array('upload_data' => $this->upload->data());
$this->load->view('upload_success', $data);
}
}
}
?>
Update as per comment:
You can check using plain php if you like ...
$errors_file = array(
0=>'Success!',
1=>'The uploaded file exceeds the upload_max_filesize directive in php.ini',
2=>'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form',
3=>'The uploaded file was only partially uploaded',
4=>'No file was uploaded',
6=>'Missing a temporary folder',
7=>'Cannot write file to disk'
);
if($_FILES['form_input_file_name']['error'] == 4) {
echo 'No file uploaded';
}
if($_FILES['form_input_file_name']['error'] == 0) {
echo 'File uploaded... no errors';
}

Resources