API REST don't work routes - codeigniter

I'm using codeigniter, for make an api rest, with the library that provide the oficial web site.
The problem is: the file routes.php doesn't redirect well. When i put localhost/API/1 into my browser apear the 404 error.
Here my controller "Apicontroller":
public function __construct() { //constructor //no tocar
parent::__construct();
$this -> load -> model("Modelocontrolador");
}
public function index_get() { //get all the info
$datos_devueltos = $this->Modelocontrolador->getPrueba(NULL, "Usuarios");
if(!is_null($datos_devueltos)){
$this->response(array("response" => $datos_devueltos), 200);
}else{
$this->response(array("response" => "No date"), 200);
}
}
public function find_get($id){ //select where
$datos_devueltos = $this->Modelocontrolador->getPrueba($id, "Usuarios");
if($id != NULL){
if(!is_null($datos_devueltos)){
$this->response(array("response" => $datos_devueltos), 200);
}else{
$this->response(array("response" => "No date"), 200);
}
}else{
$this->response(array("response" => "No dates for search"), 200);
}
}
public function index_post() { //insert in la table
if(! $this -> post("dato")){
$this->response(array("response" => "No enought info"), 200);
}else{
$datoID = $this -> Modelocontrolador -> save($this -> post("dato"),"UsuariosJJ");
if(!is_null($datoID)){
$this->response(array("response" => $datoID), 200);
}else{
$this->response(array("response" => "No found it"), 200);
}
}
}
public function index_put($id) { //"update"
if(! $this -> post("dato") || ! $id){
$this->response(array("response" => "No ha mandado informacion correcta para el update"), 200);
}else{
$datoID = $this -> Modelocontrolador -> update("Uid",$id,$this -> post("dato"),"UsuariosJJ");
if(!is_null($datoID)){
$this->response(array("response" => "Dato actualizado"), 200);
}else{
$this->response(array("response" => "Error modify"), 200);
}
}
}
public function index_delete($id) {
if(! $id){
$this->response(array("response" => "Not enought info"), 200);
}else{
$delete = $this-> Modelocontrolador -> delete("Uid",$id,"UsuariosJJ");
}
if(!is_null($delete)){
$this->response(array("response" => "Date delete"), 200);
}else{
$this->response(array("response" => "Error delete"), 200);
}
}}
And my routes file:
$route['default_controller'] = 'Apicontroller';
$route['404_override'] = '';
$route['translate_uri_dashes'] = FALSE;
/*sub-rutas*/
/*---------*/
$route["Apicontroller"]["get"] = "Apicontroller/index"; //basico
$route["Apicontroller/(:num)"]["get"] = "Apicontroller/find"; //select
$route["Apicontroller"]["post"] = "Apicontroller/index"; //insert
$route["Apicontroller/(:num)"]["put"] = "Apicontroller/index/$1"; //update
$route["Apicontroller/(:num)"]["delete"] = "Apicontroller/index/$1"; //delete

If the browser request literally uses /API then routing needs to 'see' exactly that. Also, the route rules must be explicit with the method to be called. (Hopefully the code shown reflects the mapping you had in mind.)
/*sub-rutas*/
/*---------*/
$route["API"]["get"] = "Apicontroller/index_get"; //basico
$route["API/(:num)"]["get"] = "Apicontroller/find_get/$1"; //select
$route["API"]["post"] = "Apicontroller/index_post"; //insert
$route["API/(:num)"]["put"] = "Apicontroller/index_put/$1"; //update
$route["API/(:num)"]["delete"] = "Apicontroller/index_delete/$1"; //delete
Using the above routes I created some test code. Here are those files.
The much simplified Apicontroller.
class Apicontroller extends CI_Controller
{
function __construct()
{
parent::__construct();
}
function index_get()
{
echo "API index";
}
public function find_get($id)
{ //select where
echo "API find_get $id";
}
public function index_post()
{
echo 'API index_post';
}
public function index_put($id)
{ //"update"
echo "API put $id";
}
}
I don't believe that because your Apicontroller is extending a different Class the results would change. That may be a drastic assumption.
In order to test POST calls I used these two files.
First a Testpost.php controller
class Testpost extends CI_Controller
{
public function __construct()
{
parent::__construct();
$this->load->helper('form');
}
public function index()
{
$this->load->view("test");
}
}
The very simple view (test.php) loaded by the above.
<?php
echo form_open("API");
echo form_submit('mysubmit', 'Submit Post!');
echo form_close();
Directing the browser to localhost/testpost shows a page with a single submit button. Pressing the button results in a screen with the text "API index_post".
Sending the browser to localhost/API/3 produces a screen with the text "API find_get 3".
localhost/API produces "API index".
Now the interesting thing (not related to your problem, but interesting).
Given the default
$route['default_controller'] = 'Apicontroller';
and the route
$route["API"]["get"] = "Apicontroller/index_get";
I expected that directing the browser to the home page localhost would produce "API index". But it doesn't. It results in a 404. Due to that behavior it might be wise to be more explicit with default_controller
$route['default_controller'] = 'Apicontroller/index_get';
Or add an index() function to Apicontroller that calls $this->index_get().
I did not test PUT or DELETE as my server isn't setup to handle them. But as GET and POST seem to function, in a righteous world, they will work.

seems like you are using PHil's REST_Controller library with CI 2.x, correct ?
If so, I would recommend you to use what I like to call an "index gateway" because you can't do per-Method routing with CI2:
class Apicontroller extends REST_Controller
{
function index_gateway_get($id){
$this->get_get($id);
}
function index_gateway_put($id){
$this->put_put($id);
}
// This is not a "gateway" method because POST doesn't require an ID
function index_post(){
$this->post_post();
}
function get_get($id = null){
if(!isset($id)){
// Get all rows
}else{
// Get specific row
}
}
function put_put($id = null){
if(!isset($id)){
// a PUT withtout an ID is a POST
$this->post_post();
}else{
// PUT method
}
}
function post_post(){
// POST method
}
}
The routing to make this work is really easy:
$route["API/(:num)"] = "Apicontroller/index_gateway/$1";
That's all you need. Phil's REST Library will redirect to the correct index_gateway_HTTPMETHOD depending on which method is used.
Each index_gateway_HTTPMETHOD will then redirect to the correct method.
As far as I know, this trick is the only way to have CI2 use a single /API/ entry point that works for all HTTP Methods.

Related

Laravel route : any slug takes all the requests

I have a route something like this. The $slug is a variable that is matched to the slugs stored in the database to add the pages dynamically to the website.
#slug variable for different values of page slug....
Route::get('/{slug?}', array(
'as' => 'page',
'uses' => 'AbcController#renderPage'
));
However, now I wish to add an admin side of the website and want routes to be prefixed with media-manager.
My problem is, whenever I make a call to another route in the file, the above mentioned route takes the request call and calls the renderPage method every time, no matter wherever the request is coming from.
This is my middleware where I check for whether request is coming from a URL like 'media-manager/*', if so I don't want to check for the language of the website and redirect it to the media-manager's page.
private $openRoute = ['media-manager/login', 'media-manager/postLogin', 'media-manager/media'];
public function handle($request, Closure $next)
{
foreach ($this->openRoute as $route) {
if ($request->is($route)) {
return $next($request);
}
}
// Make sure current locale exists.
$lang = $request->segment(1);
if(!isValidLang($lang)) {
$lang = getDefaultLang();
$segments = $request->segments();
array_unshift($segments, $lang);
$newUrl = implode('/', $segments);
if (array_key_exists('QUERY_STRING', $_SERVER))
$newUrl .= '?'.$_SERVER['QUERY_STRING'];
return $this->redirector->to($newUrl);
}
setLang($lang);
return $next($request);
}
This is the renderPage method where every time the request is being redirected, no matter what.
public function renderPage($slug = '')
{
if ($slug == 'login') {
return view ('site.login');
}
$page = Page::getBySlug($slug);
if(empty($page)){
return URL::to ('/');
}
if($slug == ''){//home page
$testimonial = DB::table('testimonial')->where('lang','=',$this->lang)->get();
$client_logo = DB::table('client_logo')->get();
return View::make('index', compact('data','page', 'testimonial', 'client_logo'));
}elseif($slug == 'services'){
return View::make('services', compact('page'));
}elseif($slug == 'portfolio'){
$categories = PortfolioCategory::getAll();
$portfolio = Portfolio::getAll();
return View::make('portfolio', compact('page', 'categories', 'portfolio'));
}elseif($slug == 'oshara'){
return View::make('oshara', compact('page'));
}elseif($slug == 'blog'){
$limit = 8;
$pageNum = 1;
$offset = ($pageNum-1)*$limit;
$totalPosts = BlogPost::totalPosts();
$totalPages = ceil($totalPosts/$limit);
$posts = BlogPost::getAll($offset, $limit);
$blog_posts = View::make('partials.blog_posts', compact('posts','pageNum','totalPages'));
return View::make('blog', compact('page', 'blog_posts', 'pageNum', 'totalPages'));
}elseif($slug == 'contact'){
$budgets = Budget::getAll();
return View::make('contact', compact('page', 'budgets'));
}
}
This is postLogin method in the controller that I want to call after user clicks on Login button on login page.
public function postLogin($request) {
# code...
//$request = $this->request;
$this->validate($request, [
'email1' => 'required|email',
'password' => 'required|string'
]);
if($user = User::whereEmail($request->email1)->first() ) {
if(Hash::check($request['password'], $user->getAttributes()['password'])) {
if(!$user->getAttributes()['is_active']) {
return redirect('/media-manager/login')->withErrors('Your Account is not Activated Yet!');
} else if($user->getAttributes()['is_deleted']) {
return redirect('/media-manager/login')->withErrors('Your Account is Banned!');
} else {
# Success
$cookie = Cookie::make('user_id', $user->getAttributes()['id'], 864000);
//echo "hello";
return view('site.media')->with('message', 'You have Successfully Logged In!')->withCookie($cookie);
}
} else {
return redirect('/media-manager/login')->withErrors('Your Login Information is Wrong!');
}
} else {
return redirect('/media-manager/login')->withErrors('Your Login Information is Wrong!');
}
}
Can any one please suggest me some way so that I can disable renderPage method on every call and have my normal routing perform perfectly.
In Laravel the first matching route is used. So I would guess you have your slug route defined above the others (at least above the media-manager ones), right?
So a simple solution would be to just put the slug route definition at the end of your routing file.
Another approach would be utilize conditions for the route. For more information you can read this or leave a comment!
Hope that helps!

Make an Ajax request in Symfony2

My problem is that the method doesn't return a true result.
I want to test if the email of input exists in my entity or not.
Here is the controller:
public function verificationAction(Request $request)
{
if ($this->container->get('request')->isXmlHttpRequest()) {
$email=$request->request->get('email');
$em=$this->getDoctrine()->getEntityManager();
$resp= $em->getRepository("CMSiteBundle:Prospect")->findBy(array('email'=>$email));
$response =new Response(json_encode($resp));
$response->headers->set('Content-Type', 'application/json');
return $response;
}
}
You could try an old-trick. Since in Symfony Controller Actions, You must return a Response why not fake a DEAD RESPONSE like so:
<?php
class ABCController {
public function verificationAction(Request $request) {
if ($this->container->get('request')->isXmlHttpRequest()) {
$email = $request->request->get('email');
$em = $this->getDoctrine()->getEntityManager();
$resp = $em->getRepository("CMSiteBundle:Prospect")
->findBy(array('email' => $email));
//$response = new Response(json_encode($resp));
//$response->headers->set('Content-Type', 'application/json');
// THE TRICK IS THAT DIE RUNS FIRST
// THUS SENDS YOUR RESPONSE YOU THEREBY
// STOPPING THE RETURN FROM FIRING... ;-)
return die(json_encode($resp));
}
}
}
Perhaps this very Old Trick still works for you... ;-)

laravel auth and session not persisting

The laravel session and auth I use have some problem in server, but working really fine in localhost . I will show.
Route
Route::get('/signin', 'PageController#signin');
Route::get('/signup', 'PageController#signup');
Route::get('/terms', 'PageController#terms');
Route::resource('/', 'PageController');
Route::controller('user', 'UserController');
PageController
public function index() {
if (Auth::check()) {
return View::make('user.index');
} else {
return View::make('landing');
}
}
UserController
public function postLogin() {
$data = array();
$secured = ['user_email' => $_POST['email'], 'password' => $_POST['password']];
if (Auth::attempt($secured, isset($_POST['remember']))) {
if (Auth::user()->user_status == 1 ) {
return Redirect::to('/');
} else {
$data['success'] = false;
}
} else {
$data['success'] = false;
}
return $data;
}
Auth::check() fails in pagecontoller even after login succeds. But if I change the code to
UserController
public function postLogin() {
$data = array();
$secured = ['user_email' => $_POST['email'], 'password' => $_POST['password']];
if (Auth::attempt($secured, isset($_POST['remember']))) {
if (Auth::user()->user_status == 1 ) {
return Return View::make(user.index);
} else {
$data['success'] = false;
}
} else {
$data['success'] = false;
}
return $data;
}
I get the index page and if I click the link of the home I get the landing page not the index page.
I guess I clarify my problem, I have gone through may solution replied earlier in same manner question nothing working.
I don't think its the server problem because another laravel application is working fine in same server.
Please help.
Your query seems to be incomplete, from what i understand you are able to get the index page after passing the authentication check only once, and that is by using this method:
public function postLogin() {
$data = array();
$secured = ['user_email' => $_POST['email'], 'password' => $_POST['password']];
if (Auth::attempt($secured, isset($_POST['remember']))) {
if (Auth::user()->user_status == 1 ) {
return Return View::make(user.index);
}
else {
$data['success'] = false;
}
}
else {
$data['success'] = false;
}
return $data;
}
try using a different browser to make sure there is no cookie storage restrictions in the client side and check the app/config/session.php file and see if you have configured the HTTPS Only Cookies according to your needs.
and just on an additional note this line "return Return View::make(user.index);" looks vague.

unset session on direct access to a function in codeigniter

I have 2 functions in my controller that I'm sending a session using the first one to the second function. What I am talking about is:
public function search()
{
$search_term = $this->input->post('search_term');
$this->session->set_userdata('search_term', $search_term);
redirect('search_result/');
}
and the second function:
function search_result()
{
$search_term = $this->session->userdata('search_term');
$data['search_term'] = $search_term;
$this->load->view('includes/template', $data);
}
Everything is fine but, the problem is that, I want to prevent direct access to search_result() function. I mean, I want to unset search_term session when the user calls search_result() directly. What should I do?!
You can use flashdata: http://ellislab.com/codeigniter/user-guide/libraries/sessions.html
CodeIgniter supports "flashdata", or session data that will only be available for the next server request, and are then automatically cleared. These can be very useful, and are typically used for informational or status messages
And this is the code that do what are you looking for:
public function search()
{
$search_term = $this->input->post('search_term');
$this->session->set_flashdata('search_term', $search_term);
redirect('search_result/');
}
function search_result()
{
$search_term = $this->session->flashdata('search_term') ? $this->session->flashdata('search_term') : '';
$data['search_term'] = $search_term;
$this->load->view('includes/template', $data);
}
There are many ways you can do it. Here are some
append a get parameter if it exists then search else redirect back
public function search()
{
$search_term = $this->input->post('search_term');
$this->session->set_userdata('search_term', $search_term);
redirect('search_result?status=1');
}
public function search_result()
{
$status = $this->input->get('status');
if(status == 1){
$search_term = $this->session->userdata('search_term');
$data['search_term'] = $search_term;
$this->load->view('includes/template', $data);
}else{
$this->session->unset_userdata('search_term');
redirect('search');
}
}
Protect you seach_result function and dont let user direct call it.
Using _ will do it for you.
Here is the link you can read.
public function search()
{
$search_term = $this->input->post('search_term');
$this->session->set_userdata('search_term', $search_term);
$this->_search_result($search_term);
}
function _search_result($keyword)
{
if(strlen($keyword)>0){
$data['search_term'] = $keyword;
$this->load->view('includes/template', $data);
}else{
redirect('search');
}
}
in the search function
redirect('search_result/'.$this->session->userdata('search_term'));
in the search_result function
function search_result()
{
if($this->uri->segment(3))
{
$search_term = $this->session->userdata('search_term');
$data['search_term'] = $search_term;
$this->load->view('includes/template', $data);
}
else
{
redirect('search_result/','refresh');
}
}
hope it will help you.please let me know if you face any problem.

Redirect Loop error in CodeIgniter

I worked on this for a day. I get this same problem, but I don't understand.
<?php
class Users extends CI_Controller
{
function index()
{
redirect('Users/login');
}
function login()
{
$data['title'] = 'Selamat datang di Sistem Informasi Koperasi';
$data['main_content'] = 'login';
$this->load->view('Users/template', $data);
}
function logout()
{
$this->session->sess_destroy();
$this->session->set_flashdata('info_login', 'Anda sudah keluar dari sistem');
redirect('Users/login');
}
function validate()
{
//Load User Model
$this->load->model('Users_Model');
//Validate User
$query = $this->Users_Model->validate();
if($query != '') {
//Mengambil Roles dari Groups
$roles = $this->Users_Model->roles($query->group_id);
//$this->login_model->last_login($query);
$data = array(
'username' => $query->username,
'roles' => $roles,
'is_logged_in' => true
);
$this->session->set_userdata($data);
if($roles == 'administrators') {
redirect('Administrators/index');
} elseif($roles == 'managers') {
redirect('Managers/index');
}
else {
$this->session->set_flashdata('info_login', 'Mohon maaf anda belum terdaftar sebagai Group! Silahkan hubungi admin!');
redirect('Users/login');
}
} else {
$this->session->set_flashdata('info_login', 'Maaf,username dan password yang anda masukkan salah,silahkan coba kembali!');
redirect('Users/login');
}
}
}
In Chrome and Firefox I get this message. What should i do?
This webpage has a redirect loop The webpage at
http://localhost/simpks/index.php/Users/login has resulted in too
many redirects. Clearing your cookies for this site or allowing
third-party cookies may fix the problem. If not, it is possibly a
server configuration issue and not a problem with your computer. Here
are some suggestions: Reload this webpage later. Learn more about this
problem. Error 310 (net::ERR_TOO_MANY_REDIRECTS): There were too many
redirects.
this is my view template.php
<?php
$this->load->view('includes/header',$main_content);
$this->load->view('Users/'.$main_content);
$this->load->view('includes/footer');
?>
this is my model Users_Model.php
<?php
class Users_Model extends CI_Model{
function validate(){
$this->db->where('username',$this->input->post('username'));
$this->db->where('password',md5($this->input->post('password')));
$query = $this->db->get('Users');
if($query->num_rows == 1){
$row = $query->row();
return $row;
}
}
function roles($id){
$this->db->where('id',$id);
$query = $this->db->get('Groups');
if($query->num_rows == 1){
$row = $query->row();
return $row->name;
}
}
}
?>
use include instead loader if you call it in view.
ex : include 'includes/footer';
you don't have to put redirect('Users/login'); for session checking in your view class. Just erase it.
If you need redirect, put it in another page like users/test. If session is expired in users/test call redirect method in users/test controller. For better structure, i think you should minimize php function in view.
I am also facing that problem but both page's controllers i've redirects method so I add a refresh in redirect method, try it.
read at bottom of page CI redirect with refresh
<?php
class Users extends CI_Controller
{
function index()
{
redirect('another_controller/login');
}
}
Create another controller - another_controller.php
class another_controller extends CI_Controller
{
function login()
{
$this->load->view('home');
}
}

Resources