Cannot get response from PUT request using Slim Framework - php

Am trying to update an existing entity in my database using PUT request but i have 2 issues, when am calling the request from phpStorm rest client debugger am getting an error
{"error":true,"message":"Required field(s) restaurant_id, service_rating, food_rating, music_rating is missing or empty"}
when i call the same request from Advance rest client addon on google chrome am getting
{"error":true,"message":"Task failed to update. Please try again!"}
so i can't understand if the real bug is on the verifyRequiredParams or in my function implementation . Am providing the code if someone can help me.
This is my index.php file
$app->put('/userRatings/:rating_id', 'authenticate', function($rating_id) use($app) {
// check for required params
verifyRequiredParams(array('restaurant_id', 'service_rating', 'food_rating', 'music_rating'));
global $user_id;
$restaurant_id = $app->request->put('restaurant_id');
$service_rating = $app->request->put('service_rating');
$food_rating = $app->request->put('food_rating');
$music_rating = $app->request->put('music_rating');
$db = new DbHandler();
$response = array();
// updating rating
$result = $db->updateRating($user_id, $rating_id, $restaurant_id, $service_rating, $food_rating, $music_rating);
if ($result) {
// rating updated successfully
$response["error"] = false;
$response["message"] = "Task updated successfully";
} else {
// task failed to update
$response["error"] = true;
$response["message"] = "Task failed to update. Please try again!";
}
echoRespnse(200, $response);
});
This is the function code for the verifyRequiredParams which is located in the index.php file
function verifyRequiredParams($required_fields) {
$error = false;
$error_fields = "";
$request_params = array();
$request_params = $_REQUEST;
// Handling PUT request params
if ($_SERVER['REQUEST_METHOD'] == 'PUT') {
$app = \Slim\Slim::getInstance();
parse_str($app->request()->getBody(), $request_params);
}
foreach ($required_fields as $field) {
if (!isset($request_params[$field]) || strlen(trim($request_params[$field])) <= 0) {
$error = true;
$error_fields .= $field . ', ';
}
}
if ($error) {
// Required field(s) are missing or empty
// echo error json and stop the app
$response = array();
$app = \Slim\Slim::getInstance();
$response["error"] = true;
$response["message"] = 'Required field(s) ' . substr($error_fields, 0, -2) . ' is missing or empty';
echoRespnse(400, $response);
$app->stop();
}
}
And this is my DbHandler.php file where the function is located.
public function updateRating( $user_id, $rating_id, $restaurant_id, $service_rating, $food_rating, $music_rating) {
$stmt = $this->conn->prepare("UPDATE user_ratings set service_rating = ?, food_rating = ?, music_rating = ? WHERE user_id = ? AND rating_id = ? AND restaurant_id = ?");
$stmt->bind_param("iiiiii", $user_id , $rating_id, $restaurant_id, $service_rating, $food_rating, $music_rating);
$stmt->execute();
$num_affected_rows = $stmt->affected_rows;
$stmt->close();
return $num_affected_rows > 0;
}
All my connections are ok i have checked them and also my other services are working fine

The two errors was because advance rest client use "PUT" with capital letters and php storm with lower characters even if its written with capital in php storm i notice that by changing "PUT" with "put" in the if statement of verifyRequiredParams function and now its working and updating perfectly

Add bellow code in your index.php file
$app->addBodyParsingMiddleware();

Related

read JSON input in slim framework

i am new to slim framework following a tutorial i managed to get post data to my API.but when i tried to send data as JSON it gives me an error.I tried to accpt JSON request as follows what is the correct syntax to achive this.i get error as Required field(s) name, email, password is missing or empty
$app->post('/login', function() use ($app) {
// check for required params
$json = $app->request->getBody();
$data = json_decode($json, true);
verifyRequiredParams(array('name','email', 'password'));
how i can get json data from a post request in my API from an JSON array like
{
"name":"usertest",
"email":"xxxx#xxx.xxx",
"password":"xxxxxx"
}
can i use verifyRequiredParams(array('name','email', 'password')); and $name = $app->request->post('name'); if request come as a JSON.
To read the request data you can use your $data property. It should be an object so you can use it like this:
$name = $data->name;
$email = $data->email;
EDIT:
Use $data = json_decode($json) instead of $data = json_decode($json, true) to convert the json data to object instead of an associative array.
the problem was with placing my verifyRequiredParams function i think.i fixed the issue from following code in case any one had same issue.
$app->post('/login', function() use ($app) {
if($app->request->headers->get('Content-Type')=='application/json'){
$json = $app->request->getBody();
verifyRequiredParamsjson(array('email','password'),$json);
$data = json_decode($json);
// check for required params
$email = $data->email;
$password = $data->password;
}
else{
// check for required params
verifyRequiredParams(array('email', 'password'));
// reading post params
$email = $app->request->post('email');
$password = $app->request->post('password');
}
$response = array();
$db = new DbHandler();
// check for correct email and password
if ($db->checkLogin($email, $password)) {
// get the user by email
$user = $db->getUserByEmail($email);
if ($user != NULL) {
$response["error"] = false;
$response['name'] = $user['name'];
$response['email'] = $user['email'];
$response['apiKey'] = $user['api_key'];
$response['createdAt'] = $user['created_at'];
} else {
// unknown error occurred
$response['error'] = true;
$response['message'] = "An error occurred. Please try again";
}
}
else{
$response['error'] = true;
$response['message'] = 'Login failed. Incorrect credentials';
}
echoRespnse(200, $response);
});
required parameter check,
function verifyRequiredParams($required_fields) {
$error = false;
$error_fields = "";
$request_params = array();
$request_params = $_REQUEST;
// Handling PUT request params
if ($_SERVER['REQUEST_METHOD'] == 'PUT') {
$app = \Slim\Slim::getInstance();
parse_str($app->request()->getBody(), $request_params);
}
foreach ($required_fields as $field) {
if (!isset($request_params[$field]) || strlen(trim($request_params[$field])) <= 0) {
$error = true;
$error_fields .= $field . ', ';
}
}
if ($error) {
// Required field(s) are missing or empty
// echo error json and stop the app
$response = array();
$app = \Slim\Slim::getInstance();
$response["error"] = true;
$response["message"] = 'Required field(s) ' . substr($error_fields, 0, -2) . ' is missing or empty';
echoRespnse(400, $response);
$app->stop();
}
}

Slim Framework: Insert query issue

I am new to the Slim Framework. I don't know how to perform an insert query in Slim framework.
Please can somebody show me an example or tutorial to understand it better.
I have read the Android hive tutorial but am still not clear.
I am not able to post the params when using advanced REST API.
0 Response is generated.
Below is my code for index.php file:
global $name;
$app->get('/saveEvent', function() {
global $user_id;
$response = array();
$db = new DbHandler();
$name = $app->request->post('name');
$result = $db->createUser($name);
//$response["error"] = false;
if ($result != NULL) {
$response["error"] = false;
$response["message"] = "Task created successfully";
} else {
$response["error"] = true;
$response["message"] = "Failed to create task. Please try again";
}
echoRespnse(201, $response);
});
$app->run();
Here is an example of how you would perform a post:
$app->post("/book", function () use($app, $db) {
$app->response()->header("Content-Type", "application/json");
$book = $app->request()->post();
$result = $db->books->insert($book);
echo json_encode(array("id" => $result["id"]));
});

PHP: How to delete user without delete the 'authenticate' function

Today I create a function in my web service to delete user from table in mysql.
I use SLIM framework to build my RESTful API.
this is the function in my class user:
public function deleteUser($user_id)
{
$stmt = $this->conn->prepare("DELETE
FROM users
WHERE user_id = ?");
if($stmt == FALSE)
{
die($this->conn->error);
}
else
{
$stmt->bind_param("i", $user_id);
$stmt->execute();
$num_affected_rows = $stmt->affected_rows;
$stmt->close();
return $num_affected_rows > 0;
}
}
and this is my code in index.php
$app->delete('/users/:user_id', 'authenticate', function() use($app)
{
global $user_id;
$db = new User();
$response = array();
$result = $db->deleteUser($user_id);
if ($result)
{
// user deleted successfully
$response["error"] = false;
$response["message"] = "User deleted succesfully";
}
else
{
// user failed to delete
$response["error"] = true;
$response["message"] = "User failed to delete. Please try again!";
}
echoRespnse(200, $response);
});
the problem is my authenticate function is get the user_id from user table for placed in header authorization.
function authenticate(\Slim\Route $route)
{
// Getting request headers
$headers = apache_request_headers();
$response = array();
$app = \Slim\Slim::getInstance();
// Verifying Authorization Header
if (isset($headers['Authorization']))
{
$db = new User();
// get the api key
$api_key = $headers['Authorization'];
// validating api key
if (!$db->isValidApiKey($api_key))
{
// api key is not present in users table
$response["error"] = true;
$response["message"] = "Access Denied. Invalid Api key";
echoRespnse(401, $response);
$app->stop();
}
else
{
global $user_id;
// get user primary key id
$user_id = $db->getUserId($api_key);
}
}
else
{
// api key is missing in header
$response["error"] = true;
$response["message"] = "Api key is misssing";
echoRespnse(400, $response);
$app->stop();
}
}
so everytime I tried to delete the user with 'user_id', it always goes wrong because the system will be delete users depends on API KEY which is submited in header authorization.
My Goal is : the delete function will be deleting the user with ther user id.
Does anyone know how to fix it?
Thanks :)
I am quite fishy in these lines of code:
else
{
global $user_id;
// get user primary key id
$user_id = $db->getUserId($api_key);
}
The big question for yourself is, what is the scope of the $user_id as the global variable?
Authenticate function will run before you executing the deleteUser($user_id), so no matter how hard you try, you will end up deleting the current authenticated user because $user_id = $db->getUserId($api_key) will store the current authenticated user_id to the global variable.
This will be very bad for your implementation because cureent user gonna delete itself. That's not cool man. So I suggest you the easiest workaround such as:
First declare another variable beside global $user_id named global $executor_id
Then, change your code from $user_id = $db->getUserId($api_key); to $executor_id = $db->getUserId($api_key); It assigns who will execute the delete function.
Then make your delete() function in index.php like this:
$app->delete('/users/:user_id', 'authenticate', function() use($app)
{
global $user_id;
global $executor_id;
$db = new User();
$response = array();
$user_id = // please get the user_id that would be deleted here.
$result = false;
if($user_id != $executor_id)
$result = $db->deleteUser($user_id);
if ($result)
{
// user deleted successfully
$response["error"] = false;
$response["message"] = "User deleted succesfully";
}
else
{
// user failed to delete
$response["error"] = true;
$response["message"] = "User failed to delete. Please try again!";
}
echoRespnse(200, $response);
});
Sorry, I am not familiar with SLIM Framework, but Hope it helps :)

Cannot POST data into the database

I'm trying to add some data (strings) from my android app using POST. I'm currently testing the code with the Advanced Rest Client however so the imput's from there.
EDIT: To make it more clear what my question is - what's wrong with the code that it doesn't take the values and assign them? why does it skip the first if?
EDIT 2: I am using chrome.google.com/webstore/detail/advanced-rest-client/… to test this POST.
NOTES:
echo #name; -> it does nothing, doesn't echo a thing
Right now, it automatically enters the third else saying that required field(s) are missing.
I've tried using var_dump on $name and it states the following: Unexpected token s => that didn't make any sense.
Thanks in advance for the answers, if you need more info I'll gladly provide it.
This is the code:
$app->post('/users', function() use ($app, $mysql) {
$name = $app->request->post('name');
$email = $app->request->post('email');
$beer_type = $app->request->post('beer_type');
$favorite_beer = $app->request->post('favorite_beer');
$favorite_drink = $app->request->post('favorite_drink');
echo $name;
if (!empty($name) and !empty($email) and !empty($beer_type) and !empty($favorite_beer) and !empty($favorite_drink)) {
$insert = "INSERT INTO clients(name, email) VALUES({$name}, {$email})";
$getid = "SELECT id_client FROM clients WHERE email = {$email}";
$insert2 = "INSERT INTO preferences(client_id, beer_type, favorite_beer, favorite_drink) VALUES({$idvalue}, {$beer_type}, {$favorite_beer}, {$favorite_drink})";
$request = $mysql->query($insert);
$test = false;
$id = 0;
$test2 = false;
if ($request !== false) {
$test = true;
}
if ($test === true) {
$request = $mysql->query($getid);
if ($request !== false) {
$id = $request->fetch_all(MYSQLI_ASSOC);
}
}
if ($id !== 0) {
$request = $mysql->query($insert2);
if ($request !== false) {
$test2 = true;
}
}
if ($test2 === true) {
// successfully inserted into database
$response["success"] = 1;
$response["message"] = "Product successfully created.";
// echoing JSON response
echo json_encode($response);
} else {
// failed to insert row
$response["success"] = 0;
$response["message"] = "Oops! An error occurred.";
// echoing JSON response
echo json_encode($response);
}
}else {
// required field is missing
$response["success"] = 0;
$response["message"] = "Required field(s) is missing";
// echoing JSON response
echo json_encode($response);
}
});
I've solved my issue by changing the java code. I used the Ion Library for the POST and it worked perfectly fine.

Rest API and Slim Framework

I follow the tutorial here :
http://www.androidhive.info/2014/01/how-to-create-rest-api-for-android-app-using-php-slim-and-mysql-day-23/
So I have in my index.php :
<?php
error_reporting(-1);
ini_set('display_errors', 'On');
require_once '../include/DbHandler.php';
require_once '../include/PassHash.php';
require '.././libs/Slim/Slim.php';
$app = new Slim();
// User id from db - Global Variable
$user_id = NULL;
/**
* Adding Middle Layer to authenticate every request
* Checking if the request has valid api key in the 'Authorization' header
*/
function authenticate(\Slim\Route $route) {
// Getting request headers
$headers = apache_request_headers();
$response = array();
$app = Slim::getInstance();
// Verifying Authorization Header
if (isset($headers['Authorization'])) {
$db = new DbHandler();
// get the api key
$api_key = $headers['Authorization'];
// validating api key
if (!$db->isValidApiKey($api_key)) {
// api key is not present in users table
$response["error"] = true;
$response["message"] = "Access Denied. Invalid Api key";
echoRespnse(401, $response);
$app->stop();
} else {
global $user_id;
// get user primary key id
$user_id = $db->getUserId($api_key);
}
} else {
// api key is missing in header
$response["error"] = true;
$response["message"] = "Api key is misssing";
echoRespnse(400, $response);
$app->stop();
}
}
/**
* ----------- METHODS WITHOUT AUTHENTICATION ---------------------------------
*/
/**
* User Registration
* url - /register
* method - POST
* params - name, email, password
*/
$app->post('/register', function() use ($app) {
// check for required params
verifyRequiredParams(array('name', 'email', 'password'));
$response = array();
// reading post params
$name = $app->request->post('name');
$email = $app->request->post('email');
$password = $app->request->post('password');
// validating email address
validateEmail($email);
$db = new DbHandler();
$res = $db->createUser($name, $email, $password);
if ($res == USER_CREATED_SUCCESSFULLY) {
$response["error"] = false;
$response["message"] = "You are successfully registered";
} else if ($res == USER_CREATE_FAILED) {
$response["error"] = true;
$response["message"] = "Oops! An error occurred while registereing";
} else if ($res == USER_ALREADY_EXISTED) {
$response["error"] = true;
$response["message"] = "Sorry, this email already existed";
}
// echo json response
echoRespnse(201, $response);
});
/**
* User Login
* url - /login
* method - POST
* params - email, password
*/
$app->post('/login', function() use ($app) {
// check for required params
verifyRequiredParams(array('email', 'password'));
// reading post params
$email = $app->request()->post('email');
$password = $app->request()->post('password');
$response = array();
$db = new DbHandler();
// check for correct email and password
if ($db->checkLogin($email, $password)) {
// get the user by email
$user = $db->getUserByEmail($email);
if ($user != NULL) {
$response["error"] = false;
$response['name'] = $user['name'];
$response['email'] = $user['email'];
$response['apiKey'] = $user['api_key'];
$response['createdAt'] = $user['created_at'];
} else {
// unknown error occurred
$response['error'] = true;
$response['message'] = "An error occurred. Please try again";
}
} else {
// user credentials are wrong
$response['error'] = true;
$response['message'] = 'Login failed. Incorrect credentials';
}
echoRespnse(200, $response);
});
/*
* ------------------------ METHODS WITH AUTHENTICATION ------------------------
*/
/**
* Listing all tasks of particual user
* method GET
* url /tasks
*/
$app->get('/tasks', 'authenticate', function() {
global $user_id;
$response = array();
$db = new DbHandler();
// fetching all user tasks
$result = $db->getAllUserTasks($user_id);
$response["error"] = false;
$response["tasks"] = array();
// looping through result and preparing tasks array
while ($task = $result->fetch_assoc()) {
$tmp = array();
$tmp["id"] = $task["id"];
$tmp["task"] = $task["task"];
$tmp["status"] = $task["status"];
$tmp["createdAt"] = $task["created_at"];
array_push($response["tasks"], $tmp);
}
echoRespnse(200, $response);
});
/**
* Listing single task of particual user
* method GET
* url /tasks/:id
* Will return 404 if the task doesn't belongs to user
*/
$app->get('/tasks/:id', 'authenticate', function($task_id) {
global $user_id;
$response = array();
$db = new DbHandler();
// fetch task
$result = $db->getTask($task_id, $user_id);
if ($result != NULL) {
$response["error"] = false;
$response["id"] = $result["id"];
$response["task"] = $result["task"];
$response["status"] = $result["status"];
$response["createdAt"] = $result["created_at"];
echoRespnse(200, $response);
} else {
$response["error"] = true;
$response["message"] = "The requested resource doesn't exists";
echoRespnse(404, $response);
}
});
/**
* Creating new task in db
* method POST
* params - name
* url - /tasks/
*/
$app->post('/tasks', 'authenticate', function() use ($app) {
// check for required params
verifyRequiredParams(array('task'));
$response = array();
$task = $app->request->post('task');
global $user_id;
$db = new DbHandler();
// creating new task
$task_id = $db->createTask($user_id, $task);
if ($task_id != NULL) {
$response["error"] = false;
$response["message"] = "Task created successfully";
$response["task_id"] = $task_id;
echoRespnse(201, $response);
} else {
$response["error"] = true;
$response["message"] = "Failed to create task. Please try again";
echoRespnse(200, $response);
}
});
/**
* Updating existing task
* method PUT
* params task, status
* url - /tasks/:id
*/
$app->put('/tasks/:id', 'authenticate', function($task_id) use($app) {
// check for required params
verifyRequiredParams(array('task', 'status'));
global $user_id;
$task = $app->request->put('task');
$status = $app->request->put('status');
$db = new DbHandler();
$response = array();
// updating task
$result = $db->updateTask($user_id, $task_id, $task, $status);
if ($result) {
// task updated successfully
$response["error"] = false;
$response["message"] = "Task updated successfully";
} else {
// task failed to update
$response["error"] = true;
$response["message"] = "Task failed to update. Please try again!";
}
echoRespnse(200, $response);
});
/**
* Deleting task. Users can delete only their tasks
* method DELETE
* url /tasks
*/
$app->delete('/tasks/:id', 'authenticate', function($task_id) use($app) {
global $user_id;
$db = new DbHandler();
$response = array();
$result = $db->deleteTask($user_id, $task_id);
if ($result) {
// task deleted successfully
$response["error"] = false;
$response["message"] = "Task deleted succesfully";
} else {
// task failed to delete
$response["error"] = true;
$response["message"] = "Task failed to delete. Please try again!";
}
echoRespnse(200, $response);
});
/**
* Verifying required params posted or not
*/
function verifyRequiredParams($required_fields) {
$error = false;
$error_fields = "";
$request_params = array();
$request_params = $_REQUEST;
// Handling PUT request params
if ($_SERVER['REQUEST_METHOD'] == 'PUT') {
$app = Slim::getInstance();
parse_str($app->request()->getBody(), $request_params);
}
foreach ($required_fields as $field) {
if (!isset($request_params[$field]) || strlen(trim($request_params[$field])) <= 0) {
$error = true;
$error_fields .= $field . ', ';
}
}
if ($error) {
// Required field(s) are missing or empty
// echo error json and stop the app
$response = array();
$app = Slim::getInstance();
$response["error"] = true;
$response["message"] = 'Required field(s) ' . substr($error_fields, 0, -2) . ' is missing or empty';
echoRespnse(400, $response);
$app->stop();
}
}
/**
* Validating email address
*/
function validateEmail($email) {
$app = Slim::getInstance();
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$response["error"] = true;
$response["message"] = 'Email address is not valid';
echoRespnse(400, $response);
$app->stop();
}
}
/**
* Echoing json response to client
* #param String $status_code Http response code
* #param Int $response Json response
*/
function echoRespnse($status_code, $response) {
$app = Slim::getInstance();
// Http response code
$app->status($status_code);
// setting response content type to json
$app->contentType('application/json');
echo json_encode($response);
}
$app->run();
?>
But, like others people, I've got some error when I try to call the register method :
{
error: true
message: "Required field(s) name, email, password is missing or empty"
}
It seems that $_REQUEST is empty so the parameters are not sent...
I try with curl or with RestClient app extension in Google Chrome, it still doesn't work...
Any idea to make it work ?
Another way of accessing the post params, which worked for me is:
// reading post params
$name = $app->request->params('name');
$email = $app->request->params('email');
$password = $app->request->params('password');
And the response you got
{
error: true
message: "Required field(s) name, email, password is missing or empty"
}
means your post parameters are empty. Try using Postman - REST Client to test your REST API calls. I faced the same problem while using Firefox Add-On "Poster"
Note: while testing the api make sure you are properly making a POST request and not GET request.
You should remove '.' in DbConnect.php and DbHandler.php
DbConnect.php
include_once dirname(__FILE__) . './Config.php';
-> include_once dirname(__FILE__) . '/Config.php';
DbHandler.php
include_once dirname(__FILE__) . './Config.php';
-> include_once dirname(__FILE__) . '/Config.php';
That make 2 file include exact what they need. I change this and the API run very good.
Note: You should add header when you call api by Chrome add-on.
Content-Type: application/x-www-form-urlencoded
You need to parse the raw data from php input stream.
if (!empty($_GET)) {
$_INPUT = $_GET;
} else {
$_INPUT = json_decode(file_get_contents('php://input'), TRUE);
}
see this
and this
I used firefox and POSTER addon for test REST API. After I open poster window from tools->poster. In the url put my path to www/task_manager/v1/register and in parameters tab I pass three parameter for name, email, password and after that I click on body from parameters and click post button.
its worked for me. and i saw good result.
Note:
I cant use chrome advanced REST, because for unknown reason chrome didnt let me to install that addon!

Categories