Codeigniter mobile redirect with caching - codeigniter

I have got my site(mysite.com) to redirect to mysite.com/Mobile for mobile browsers using codeigniters useragent library from my default controller.
When I cache my output from the controller the redirect doesnt work as the browser is served the cached file.
Is there a proper way to go about redirecting from the config/routes.php file? Will this redirect mobile visitors?
My controller
class Child extends Controller {
function child()
{
parent::Controller();
//$this->output->cache(7200);
$agent = $this->agent->browser() . ' ver ' . $this->agent->version();
}
function index()
{
if ($this->agent->is_mobile())
{
header('Location: ' . site_url() . 'Mobile/', TRUE, 301);
exit(0);
}else{
$this->output->cache(7200);
$this->load->view('home',$data);
}
}

I wouldn't suggest using CodeIgniter's output caching. That runs before the Controller, therefore you will never get in the index(). Routing can't deal with this situation as it isn't able to detect if the client is mobile.
It's a better idea to use the other caching method that CodeIgniter offers, as it's more granular, you can cache the single views. http://codeigniter.com/user_guide/libraries/caching.html
function index()
{
// should put this in the __construct() of this controller or in your MY_Controller.php
$this->load->driver('cache', array('adapter' => 'apc', 'backup' => 'file'));
if ($this->agent->is_mobile())
{
redirect('Mobile');
}
else
{
// if this doesn't get us the output, recreate and store it
if(!$output = $this->cache->get('controllername_index_output'))
{
$output = $this->load->view('home', $data, TRUE);
$this->cache->save('controllername_index_output', $output, 7200);
}
// now we surely have the output ready, whether it was cached or not
$this->output->set_output($output);
}
}

Related

How to fetch session data in codeigniter?

I am trying to create a login process using codeigniter framework. Form validation is working but there is a problem in session. I can't fetch username after "Welcome-".
controller : Main.php
<?php
class Main extends CI_Controller
{
public function login()
{
$this->load->view('login');
}
public function login_validation()
{
$this->form_validation->set_rules('username','Username','required');
$this->form_validation->set_rules('password','Password','required');
if ($this->form_validation->run())
{
$username = $this->input->post('username');
$password= $this->input->post('password');
//model
$this->load->model('myModel');
if ($this->myModel->can_login($username,$password))
{
$session_data = array('username' => $username);
$this->session->set_userdata('$session_data');
redirect(base_url().'main/enter');
}
else
{
$this->session->set_flashdata('error','Invalid Username Or Password');
redirect(base_url().'main/login');
}
}
else
{
$this->login();
}
}
function enter()
{
if ($this->session->userdata('username')!=' ')
{
echo '<h2> Welcome- '.$this->session->userdata('username').'</h2>';
echo 'Logout';
}
else
{
redirect(base_url().'main/login');
}
}
function logout()
{
$this->session->unset_userdata('username');
redirect(base_url().'main/login');
}
}
?>
Add session library in the constructor
<?php
class Main extends CI_Controller
{
public function __construct()
{
parent::__construct();
// Load form helper library
$this->load->helper('form');
// Load form validation library
$this->load->library('form_validation');
// Load session library
$this->load->library('session');
$username = $this->session->userdata('username');
if (empty($username)) {
redirect('main/logout');
}
}
}
Another method you can load the session library in autoload.php file
File location: application/config/autoload.php
$autoload['libraries'] = array('database', 'email', 'session');
I suggest a slight code rearrangement for enter() that provides a better test for the user name using a tiny bit less code.
function enter()
{
if(empty($this->session->userdata('username')))
{
//base_url() accepts URI segments as a string.
redirect(base_url('main/login'));
}
// The following code will never execute if `redirect()` is called
// because `redirect()` does not return, it calls `exit` instead.
// So, you do not need an `else` block
echo '<h2> Welcome- '.$this->session->userdata('username').'</h2>';
echo 'Logout';
}
empty() will be true for an empty string, NULL, False and a couple of other things. In this case, you are most interested in an empty string or NULL. (empty() documentation HERE.)
You might want to consider adding 'trim' to your validation rules because it strips empty whitespace from the input string. That will remove the possibility of someone trying to input a username using only space characters.
Otherwise, your code should work. If it does not then it's very likely you do not have CodeIgniter sessions configured properly. There are many session setup questions answered here on Stack Overflow that will help you get it running.

Laravel Ajax controller with single route

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.

Laravel 4 : Route to localhost/controller/action

I'm more or less new to Laravel 4. I've never used routes before but normally what I'm used to is url/controller/action and then the backend routing for me. I've read the documentation for routes and controllers a few times as well as read through some tutorials and so, I'm trying to figure out how to get this to work without writing a route for every controller and action.
I tried something like
Route::get('{controller}/{action}', function($controller, $action = 'index'){
return $controller."#".$action;
});
Now then, I know this is wrong since it doesn't work, but what am I missing? On most tutorials and stuff I'm seeing an route for more or less every controller and action like:
Route::get('/controller/action' , 'ControllerName#Action');
Which seems silly and like a waste of time to me.
Is there anyway to achieve what I want?
If you are looking for a more automated routing, this would be the Laravel 4 way:
Route:
Route::controller('users', 'UsersController');
Controller (in this case UsersController.php):
public function getIndex()
{
// routed from GET request to /users
}
public function getProfile()
{
// routed from GET request to /users/profile
}
public function postProfile()
{
// routed from POST request to /users/profile
}
public function getPosts($id)
{
// routed from GET request to: /users/posts/42
}
As The Shift Exchange mentioned, there are some benefits to doing it the verbose way. In addition to the excellent article he linked, you can create a name for each route, for example:
Route::get("users", array(
"as"=>"dashboard",
"uses"=>"UsersController#getIndex"
));
Then when creating urls in your application, use a helper to generate a link to a named route:
$url = URL::route('dashboard');
Links are then future proofed from changes to controllers/actions.
You can also generate links directly to actions which would still work with automatic routing.
$url = URL::action('UsersController#getIndex');
app\
controllers\
Admin\
AdminController.php
IndexController.php
Route::get('/admin/{controller?}/{action?}', function($controller='Index', $action='index'){
$controller = ucfirst($controller);
$action = $action . 'Action';
return App::make("Admin\\{$controller}Controller")->$action();
});
Route::get('/{controller?}/{action?}', function($controller='Index', $action='index'){
$controller = ucfirst($controller);
$action = $action . 'Action';
return App::make("{$controller}Controller")->$action();
});
I come from .Net world and routing is typically done:
/{Controller}/{action}/{id}
Which looks like:
/Products/Show/1 OR /Products/Show/Beverages
In Laravel I accomplish this routing like so:
Route::get('/{controller?}/{action?}/{id?}', function ($controller='Home', $action='index', $id = null) {
$controller = ucfirst($controller);
return APP::make("{$controller}Controller")->$action($id);
});
The controller would look roughly like so:
class ProductsController extends BaseController {
public function Show($id) {
$products = array( 1 => array("Price" => "$600","Item" => "iPhone 6"),
2 => array("Price" => "$700", "Item" => "iPhone 6 Plus") );
if ($id == null) {
echo $products[1]["Item"];
} else {
echo $products[$id]["Item"];
}
}
}

codeigniter best way to create controller for editing a db row

Im new to codeigniter and im developing my first web application with it and want to make sure im doing best practices the 1st time so i dont have to go back to make corrections down the road. with that said, here is what im doing.
I want to edit a note in the DB, then after the record has been updated redirect to a different page.
my model is coded correctly so im not worried there, but the controller looks like this (and this is probably not correct:
public function edit($id) {
$this->load->model('Notes_model');
if (isset($_POST["edit"]))
{
$data['data'] = $this->Notes_model->edit($id);
$url = "/Notes/view/" . $id;
redirect($url);
}
$data['notes'] = $this->Notes_model->viewNotes($id);
$this->load->view('templates/header');
$this->load->view('notes/edit', $data);
$this->load->view('templates/footer');
}
hopefull this makes sense, basically what I'm wanting to do here is:
1.) Show the edit note page
2.) if i edited that page by hitting submit
a.) update the db
b.) redirect to a different page.
does this look pretty good or should i make some better changes?
Although your controller code is fine but one thing you have to take care that you should load model in the constructor of your controller so you don't have to include the model in each function same recommendations for the libraries, helpers this is the best practice
class myclass extends CI_Controller {
function __construct() {
parent::__construct();
$this->load->model('Notes_model');
$this->load->helper(form);
}
public function myfunction(){
}
}
Here is the starting tutorial with MVC standards advanced-codeigniter-techniques-and-tricks
<?php
class Home extends CI_Controller
{
function __construct() {
parent::__construct();
$this->m_auth->notLogin();
$this->load->library('form_validation');
$this->load->library('ajax_pagination');
$this->load->library('dateconverter');
$this->load->helper('template');
$this->load->helper('check');
$this->load->model('mymodels/crud_model');
$this->lang->load('personal', $this->m_auth->get_language());
$this->lang->load('global', $this->m_auth->get_language());
}
function index()
{
$this->get_recs();
}
function get_recs()
{
//get for view or first page to be showed
}
/**
* Register New User
*/
function updateRecords()
{
$this->form_validation->set_rules('ministery','<span class="req">(Ministry)</span>','trim|required');
$this->form_validation->set_rules('directorate','<span class="req">(Directorate)</span>','trim|required');
if($this->form_validation->run()==FALSE)
{
header_tpl($this->m_auth->get_language(),'a');
banner_tpl($this->m_auth->get_language(),'a');
left_tpl($this->m_auth->get_language(),'a');
$content = $this->load->view('personal/edit_personal', $this->POST,true);
content_tpl($content);
footer_tpl();
}
else
{
$form_data = array(
'ministry' => $this->input->post('ministery'),
'directorate' => $this->input->post('directorate'),
'job_province' => $this->input->post('job_province'),
'job_district' => $this->input->post('job_district'),
'first_name' => $this->input->post('fname'),
'last_name' => $this->input->post('lname')
);
if($this->crud_model->update_recs('ast_emp_property',$form_data)==TRUE)
{
$this->session->set_flashdata("msg","<span class='m_success'>".$this->lang->line('global_insert_success')."</span>");
redirect('/home/success_reg/'.$id.'','refresh');
}
else
{
$this->session->set_flashdata("msg","<span class='m_error'>".$this->lang->line('global_insert_error')."</span>");
redirect('home','refresh');
}
}
}
}
?>

How to change the value of a variable inside a controller from a view file (html)?

I followed this tutorial: http://codeigniter.com/wiki/Internationalization_and_the_Template_Parser_Class/
The controller that loads the language is this one:
<?php
class Example extends Controller {
function Example() {
parent::Controller();
# Load libraries
$this->load->library('parser');
# Load language
$this->lang->load('example', 'english');
}
function index() {
# Load variables into the template parser
$data = $this->lang->language;
# Display view
$this->parser->parse('example', $data);
}
}
?>
In order to change the language I have to manually change english to say spanish in the controller.
What's the best way the user can do this from the index.php file (view)?
The best thing to do is have the user select a supported language on some page, set it as a session variable and call it when ever you need to load a language
$language = $this->session->userdata("language");
$this->lang->load("example", $language);
$data = $this->lang->language;
$this->parser->parse("example", $data);
EDITED BELOW
If you're using CodeIgniter and you're new to this, I wouldn't suggest messing with the index.php file.
You want to do it inside your controller by loading a form where they can pick their language and storing it in the session. I'd also suggest autoloading your session library.
The controller:
<?php
class Home extends Controller {
function Home()
{
parent::Controller();
$this->load->library("session");
}
function index()
{
$language = $this->session->userdata("language");
$this->lang->load("example", $language);
$data = $this->lang->language;
$this->parser->parse("example", $data);
}
function set_lang()
{
if( ! $this->form_validation->run())
{
$this->load->view("select_language_form");
}
else
{
$language = $this->input->post('language', TRUE);
$this->session->set_userdata('language', $language);
redirect('home' 'location');
}
}
}

Resources