Codeigniter - configure enable_query_strings and form_open - model-view-controller

I want to be able to user query strings in this fashion. Domain.com/controller/function?param=5&otherparam=10
In my config file I have
$config['base_url'] = 'http://localhost:8888/test-sites/domain.com/public_html';
$config['index_page'] = '';
$config['uri_protocol'] = 'PATH_INFO';
$config['enable_query_strings'] = TRUE;
The problem that I am getting is that form_open is automatically adding a question mark (?) to my url.
So if I say:
echo form_open('account/login');
it spits out: http://localhost:8888/test-sites/domain.com/public_html/?account/login
Notice the question mark it added right before "account".
How can I fix this?
Any help would be greatly appreciated!

The source of your problem is in the Core Config.php file where the CI_Config class resides. The method site_url() is used by the form helper when you are trying to use form_open function.
Solution would be to override this class with your own. If you are using CI < 2.0 then create your extended class in application/libraries/MY_Config.php, otherwise if CI >= 2.0 then your extended class goes to application/core/MY_Config.php.
Then you need to redefine the method site_url().
class MY_Config extends CI_Config
{
function __construct()
{
parent::CI_Config();
}
public function site_url($uri='')
{
//Copy the method from the parent class here:
if ($uri == '')
{
if ($this->item('base_url') == '')
{
return $this->item('index_page');
}
else
{
return $this->slash_item('base_url').$this->item('index_page');
}
}
if ($this->item('enable_query_strings') == FALSE)
{
//This is when query strings are disabled
}
else
{
if (is_array($uri))
{
$i = 0;
$str = '';
foreach ($uri as $key => $val)
{
$prefix = ($i == 0) ? '' : '&';
$str .= $prefix.$key.'='.$val;
$i++;
}
$uri = $str;
}
if ($this->item('base_url') == '')
{
//You need to remove the "?" from here if your $config['base_url']==''
//return $this->item('index_page').'?'.$uri;
return $this->item('index_page').$uri;
}
else
{
//Or remove it here if your $config['base_url'] != ''
//return $this->slash_item('base_url').$this->item('index_page').'?'.$uri;
return $this->slash_item('base_url').$this->item('index_page).$uri;
}
}
}
}
I hope this helps and I think you are using CI 2.0 that wasn't officially released, this was removed in the official CI 2.0 version

Simpler might be to just set follwing in your config.php
$config['enable_query_strings'] = FALSE;
Was the solution in my case.

If you want to use query string in your url structure, then you should manually type your url structure in the following order:
<domain.com>?c={controller}&m={function}&param1={val}&param2={val}
in the action of the resepective controller you should get the parameter as $_GET['param1']
your code now should look like this
form_open(c=account&m=login&param1=val)
Please let me know if it doesnt work for you.

Related

How add multiple actions In URL?

How can I add more than one action to a URL? As I described in the title, I want to add more than one action to a URL. How do I do that?
As a further clarification, I define actions for some parts in an HTML file, and by setting an action, I handle the request in the php file!
Example:
example.com/?order=1&price=high
I appreciate your help.
As i ask and get help from my friend, we can use function like this to solve our problem:
function shapeSpace_add_var($url, $key, $value) {
$url = preg_replace('/(.*)(?|&)'. $key .'=[^&]+?(&)(.*)/i', '$1$2$4', $url .'&');
$url = substr($url, 0, -1);
if (strpos($url, '?') === false) {
return ($url .'?'. $key .'='. $value);
} else {
return ($url .'&'. $key .'='. $value);
}
}
example:
$url = 'http://example.com/whatever/?hello=world';
shapeSpace_add_var($url, 'goodbye', 'nightclub');
Result:
http://example.com/whatever/?hello=world&goodbye=nightclub

Joomla 2.5 method save()

Is there a way to show the changed values after saving within the Joomla save method?
For example, when I edit a "maxuser" field and save it, I´d like to show the old and the new value.
I tried this by comparing "getVar" and "$post", but both values are the same.
function save()
{
...
$maxuser1 = JRequest::getVar('maxuser');
$maxuser2 = $post['maxuser'];
...
if($maxuser1 != $maxuser2) {
$msg = "Not the same ...";
}
...
}
It's better to override JTable, not the Model. Heres sample code:
public function store($updateNulls = false) {
$oldTable = JTable::getInstance(TABLE_NAME, INSTANCE_NAME);
$messages = array();
if ($oldTable->load($this->id)) {
// Now you can compare any values where $oldTable->param is old, and $this->param is new
// For example
if ($oldTable->title != $this->title) {
$messages[] = "Title has changed";
}
}
$result = parent::store($updateNulls);
if ((count($messages) > 0) && ($result === true)){
$message = implode("\n", $messages);
return $message;
} else {
return $result;
}
}
This will return message string if there are any, true if there are no messages and save succeeded and false if saving failed. So all you have to do is check returned value in model and set right redirect message.
In the controller you can use the postSaveHook which gives you access to the validated values.

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.

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