I cannot get my PHP Rest API to work, it is just returning empty body
with a successful HTTP request(200).
When I just echo something out it returns it fine. I am using Slim (PHP micro framework), MySQL,apache. Database table is created in phpmyadmin.
index.php
<?php
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;
require '../vendor/autoload.php';
require '../src/config/db.php';
$app = new \Slim\App;
$app->get('/hello/{name}', function (Request $request, Response $response) {
$name = $request->getAttribute('name');
$response->getBody()->write("Hello, $name");
return $response;
});
// Customer Routes
require '../src/routes/dates.php';
$app->run();
db.php it also contains dbhost, dbuser, dbpass and dbname
variables above
<?php
class db
{
// Properties
var $dbhost = 'localhost';
var $dbuser = 'root';
var $dbpass = 'parool1';
var $dbname = 'slimapp';
// Connect
public function connect()
{
$mysql_connect_str = "mysql:host=$this->dbhost;dbname=$this->dbname";
$dbConnection = new PDO($mysql_connect_str, $this->dbuser, $this->dbpass);
$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $dbConnection;
}
}
dates.php
<?php
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;
$app = new \Slim\App;
// Get All Calendar Dates
$app->get('/api/date', function (Request $request, Response $response) {
$sql = "SELECT * FROM `calendardates`";
try {
// Get DB Object
$db = new db();
// Connect
$db = $db->connect();
$stmt = $db->query($sql);
$dates = $stmt->fetchAll(PDO::FETCH_OBJ);
$db = null;
echo json_encode($dates);
} catch (PDOException $e) {
echo '{"error": {"text": ' . $e->getMessage() . '}';
}
});
Solution:
Change collation of database table to utf8 (if you want to use charcaters like "ö, ä, ü" in your database table).
I changed
$dbConnection = new PDO($mysql_connect_str, $this->dbuser, $this->dbpass);
to
$dbConnection = new PDO($mysql_connect_str, $this->dbuser, $this->dbpass, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
to fix the problem.
To return a json try to replace
echo json_encode($dates);
With
return $response->withJson($dates);
As suggested by mim in comment.
Related
I'm trying to make a API server that is supposed to connect to a data base, using SLIM framework following this tutorial. Actually I made a endpoint who get data from the data base, but can't insert new one.
Every time when I try to insert new data the POST parameters are nulls and the data base only send a error message.
In my groupes.php I have the following:
<?php
use Slim\Http\Request;
use Slim\Http\Response;
// Routes
$app->get('/[{name}]', function (Request $request, Response $response, array$args) {
// Sample log message
$this->logger->info("Slim-Skeleton '/' route");
// Render index view
return $this->renderer->render($response, 'index.phtml', $args);
});
$app->group('/api', function () use ($app) {
$app->group('/v1', function () use ($app) {
$app->get('/clients', 'getClients');
$app->post('/make', 'addClient');
});
});
The code above is just to define two endpoits: getClients and addClient.
And in my index.php I have:
function getConnection(){
$dbhost = "127.0.0.1";
$dbuser = "root";
$dbpass = "dzpga883yRusPHhv";
$dbname = "pruebaandroid";
$dbh = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $dbh;
}
//method: GET
//domain: mi-api/api/v1/clients
function getClients($response){
$sql = "SELECT * FROM cliente";
try{
$stmt = getConnection()->query($sql);
$client = $stmt->fetchAll(PDO::FETCH_OBJ);
$db = null;
return json_encode($client);
}
catch(PDOException $e){
echo '{"error":{"text":'. $e->getMessage() .'}}';
}
}
//method: POST
//domain: mi-api/api/v1/make
function addClient($request) {
$client = json_decode($request->getBody());
$sql = 'INSERT INTO cliente (nombre, apellido, cedula, direccion, telefono, email) VALUES (:nombre, :apellido, :cedula, :direccion, :telefono, :email)';
try {
$db = getConnection();
$stmt = $db->prepare($sql);
$stmt->bindParam(":nombre", $client->nombre);
$stmt->bindParam(":apellido", $client->apellido);
$stmt->bindParam(":cedula", $client->cedula);
$stmt->bindParam(":direccion", $client->direccion);
$stmt->bindParam(":telefono", $client->telefono);
$stmt->bindParam(":email", $client->email);
$stmt->execute();
$client->id = $db->lastInsertId();
$db = null;
echo json_encode($client);
}
catch(PDOException $e){
echo '{"error":{"text":'. $e->getMessage() .'}}';
}
}
So, using postman to do a GET request to mi-api/api/v1/clientes retrieve all the data as spected, but whhen I try with a POST request mi-api/api/v1/make?nombre=asdf&apellido=asdf&cedula=asdf&direccion=asdf&telefono=asdf&email=asdf it's supposed to insert the new information but postman give me the following error:
{"error":{"text":SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'nombre' cannot be null}}
Looks like the addClient function it's not geting the parameters, so it's taking it as null. Why is this happening? I don't know what is wrong here, any response is welcome.
See the image
PD: yes, the DB is well formated, it have a id as PK auto increment and I tryed to print echo client->nombre and prints nothing but the error.
You are adding your parameters as GET parameters (added on url).
Use the BODY -> form-data tab to specify your POST parameters (The same you have in PARAMS tab)
I'm new to PHP Slim framework and I've written code to connect to database but it shows the following error in console (The database exists, still getting error):
Here's my code:
<?php
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;
require '../vendor/autoload.php';
function dbConnect(){
$host='127.0.0.1';
$user='root';
$pass='';
$dbname='testdbmysql';
$pdo= new PDO("mysql:host=$host; dbname= $dbname", $user, $pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
return $pdo;
}
$app = new \Slim\App;
$app->post('/hello/{id}', function (Request $request, Response $response, $args) {
echo "hello";
$names = $request->getParsedBody();
$db=dbConnect();
$names_arr=[];
$names_arr['name1']= filter_var($names['name1'], FILTER_SANITIZE_STRING);
$names_arr['name2']= filter_var($names['name2'], FILTER_SANITIZE_STRING);
$response->getBody()->write("Hello , ".$names_arr['name1']);
$query=mysqli_prepare($db, "INSERT into info(fname, lname) VALUES(?, ?)");
mysqli_stmt_bind_param($query, "ss", $names_arr['name1'], $names_arr['name2']);
$result=mysqli_stmt_execute($query);
$rows=mysqli_stmt_insert_id($query);
echo "Rows: ".$rows;
return $response;
});
$app->run();
?>
When I searched on Internet, I found solutions to same error caused by Laravel framework, but not about Slim. Is there something I can do?
You should remove the whitespace
$pdo= new PDO("mysql:host=$host; dbname=$dbname", $user, $pass);
The error output is displaying the whitespace, too. So that should be the mistake.
Also, do not Mix up PDO and mysqli. You are passing a PDO-Connection to mqsqli functions, thats why you get " Expected mysqli, got PDO."
I would stick with mysqli and set up a connection via mysqli_connect().
I used Php Slim Framework for my API. I install the Slim Framework to my web root directory on my server and copy the index.php file I coded.
Index.php:
<?php
require 'vendor/autoload.php';
$app = new \Slim\Slim();
$app->contentType('application/json');
$app->get('/users', 'getUsers');
$app->get('/user/:id', 'getUser');
$app->run();
function getConnection() {
$dbhost="localhost";
$dbuser="";
$dbpass="";
$dbname="";
$dbh = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $dbh;
}
function getUsers() {
$sql = "select * FROM manga";
try {
$db = getConnection();
$stmt = $db->query($sql);
$users = $stmt->fetchAll(PDO::FETCH_OBJ);
$db = null;
echo json_encode($users);
}
catch(PDOException $e) {
echo json_encode($e->getMessage());
}
}
?>
I am getting 500 (Internal Server Error).
Edit: I changed "$app = new Slim();" to the "$app = new \Slim\Slim();" then receive the below error.
I am using EasyEngine(Nginx).
Edit-2:Now 500 Internal gone but another error showing.
XMLHttpRequest cannot load http://api.mangayurdu.com/users. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://deneme.mangayurdu.com' is therefore not allowed access.
Here is my code that getting JSON data:
.factory('MY', function($http){
var factory = {};
var url = 'http://api.mangayurdu.com/users?callback=JSON_CALLBACK';
factory.isimler = $http.get(url);
return factory;
})
From the posted code it looks like Slim can't find a function called getUser. getUsers() is defined in your code, but no getUser() function.
try putting this in the start of your PHP page
<?php header('Access-Control-Allow-Origin: *');?>
Making requests from angular http to local Apache 2.4 server running php restapi with slim framework. the requests take 15+ seconds to come back. however when I use postman to test the api the responses take 20ms which is what I expect. I'm brand new to php, is there some configuration I'm missing?
<?php
require 'vendor/autoload.php';
$app = new Slim\Slim();
// ==============================
// Connection ===================
// ==============================
function connect()
{
$servername = "localhost";
$username = "root";
$password = "******";
try {
$conn = new PDO("mysql:host=$servername;dbname=contacts", $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//echo "Connected successfully<br>";
} catch (PDOException $e) {
echo "Connection failed: " . $e->getMessage();
}
return $conn;
}
$app->get('/contacts', function () use ($app) {
getContacts(connect(), $app);
});
$app->run();
function getContacts($conn, $app)
{
$app->response()->header("Content-Type", "application/json");
$app->response()->header('Access-Control-Allow-Origin', '*');
$app->response()->header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
$app->response()->header('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
$app->response()->header('Access-Control-Allow-Credentials', true);
try {
$stmt = $conn->prepare("SELECT * FROM contacts");
$stmt->execute();
echo json_encode($stmt->fetchAll());
} catch (PDOException $e) {
echo $e->getMessage();
}
$conn = null;
}
The Request
$http({
method: 'GET',
url : "http://localhost/Contacts_PHP/contactsAPI.php/contacts"
}).success(function (data) {
$scope.contacts = data;
console.log($scope.contacts);
}).error(function (ex) {
console.log(ex);
});
Try closing the connection by sending the following header:
$app->response->headers->set('Connection', 'close');
But first, set your response body by using the setBody() method, instead of using echo:
$app->response->setBody(json_encode($data));
The code that I will post works but I want to know if it's okay and safe. I will use it to connect my Android APP with my MySQL database.
Here I create the PDO connection. I don't know if I should create it in the construct or using a method. Right now I'm using the connect() method and get() to return the same object. Should I close the connection? Why?
db_config.php
private $db;
function __construct(){
}
function __destruct(){
}
public function connect(){
$host = "XXXXXXXX";
$dbname = "XXXXXXXX";
$username = "XXXXXXX";
$password = "XXXXXXXX";
$options = array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8');
try{
$this -> db = new PDO("mysql:host={$host};dbname={$dbname};charset=utf8", $username, $password, $options);
} catch (PDOException $ex) {
die("Failed to connect to the database: " . $ex->getMessage());
}
$this-> db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this -> db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
return $this->db;
}
public function get(){
return $this -> db;
}
trainer_functions.php
In this code I have the functions that I will use to interact with the database. I initialize the connection in the construct and then I use the get() method to return the same connection everytime I need it. Is this okay?
private $db;
function __construct(){
require_once 'db_config.php';
$this->db = new DB_Connect();
$this->db->connect();
}
public function storeUser($json){
$obj = json_decode($json);
$email = $obj -> {"email"};
$pass = $obj -> {"password"
$query = "INSERT INTO USUARIOS (email, pass) VALUES (:email , :pass)";
$query_params = array(
':email' => $email,
':pass' => $pass
);
try {
$stmt = $this -> db -> **get()** -> prepare($query);
$result = $stmt -> execute($query_params);
//json response
}
catch (PDOException $ex) {
//json response
}
The last part of my test code are the calls to the functions using tags. I create a trainer_functions object, then I collect the parameters via POST and call the function with the object. Here I have two questions:
- I send a JSON. Should I send the tag inside or outside the JSON?
- I think here should close the connection because the request has already been completed. It is true?
I would make a good web service because it is the last project of my course and later it will be a personal project with some iOS integration.
Thank you very much.
I've no idea on other files you included (they are too hard to read) but to answer the question from the title: PDO is already a class. You don't need no more.
So, db_config.php
<?php
$host = "XXXXXXXX";
$dbname = "XXXXXXXX";
$username = "XXXXXXX";
$password = "XXXXXXXX";
$charset = 'utf8';
$options = array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES $charset',
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
);
$dsn = "mysql:host=$host;dbname=$dbname;charset=$charset"
$db = new PDO($dsn, $username, $password, $options);
is all you need.