How to insert data from external API into Database using cURL

I have an external API, but i am trying to get the array of data and insert it into my database.

I have written a curl script that gets data from the API as seen below at
index.php page

<?php
$ch = curl_init();

$url = "http://example.com/api/properties/";

curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$resp = curl_exec($ch);

if($e = curl_error($ch)){
    echo $e;
}
else {
    $decoded = json_decode($resp, true);
    print_r($decoded);
}

curl_close($ch);

The code above displays all the data from the API in my web browser but i am looking to save some datas into the database.

I have a data.php page which connects to the database as seen below

<?php
if(isset($_POST['county'])){
    $db = new Mysqli("localhost", "root", "", "api-call");
    $county = $db->real_escape_string($_POST['county']);
    $query= "INSERT INTO details SET county='$county'";
    $db->query($query);
}
?>

But anytime i refresh the index.php page this does not insert into the database. I tried modifying the index.php page to have this code

<?php
$ch = curl_init();

$url = "http://example.com/api/properties/";

curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$resp = curl_exec($ch);

if($e = curl_error($ch)){
    echo $e;
}
else {
    $decoded = json_decode($resp, true);
    foreach($decoded["data"] as $decoded){
        $data = array(
            'county' => $decoded['county'],
        );
    
    }
    
}


curl_close($ch);

But still the data will not save into the database, please how can i solve this?

Have you checked the value of $county? Maybe it is empty? You should use prepared statements to protect your data. real_escape_string is not as safe as using prepared statements.

Can you show us a sample of the data you are trying to set into the database. my guess is that there are characters that are messing up the query. Have you dumped the $query to see what was actually created for a query. That would be next step!

1 Like

@ErnieAlex
I tried using prepared statement here but the data is not entering the database table.

Here is the code

<?php

$servername = "localhost";
$username = "root";
$password = "root";

try {
    $conn = new PDO("mysql:host=$servername;dbname=api-call", $username, $password);
    // set the PDO error mode to exception
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    echo "Connected successfully"; 
}
catch(PDOException $e)
{
    echo "Connection failed: " . $e->getMessage();
}



$ch = curl_init();

$url = "http://example.com/api/properties";

curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$resp = curl_exec($ch);

if($e = curl_error($ch)){
    echo $e;
}
else {
    $decoded = json_decode($resp,true);
    // print_r($decoded);
    foreach($decoded["data"] as $decode){
      $stmt = $conn->prepare("INSERT INTO details (county) VALUES (?)");
      $stmt->bind_param("sss", $county);
  
      $county = $decode['county'];

      
        

      // //set parameters
      

      $stmt->execute();
      $stmt->close();
      $conn->close();

    }
    
}

curl_close($ch);

Here is the sample of data

{
    "current_page": 1,
    "data": [
        {
            "uuid": "d8d9c545-3832-3d85-a25a-aac181479be7",
            "property_type_id": "4",
            "county": "Oklahoma",
            "country": "Palm Front",
            "town": "Jigawa",
            "description": "Lorem Ipsum",
            "address": "1 Skitiam Old Apt. 212",
}
]
}

Well, that code make no sense. Sorry. I will explain…

$stmt = $conn->prepare("INSERT INTO details (county) VALUES (?)");
      $stmt->bind_param("sss", $county);

[/quote]
So, you are passing three STRING parms, but, only sending one. The “sss” means that you are sending three strings to the prepared statement. Also, You do not need to loop this way. It defeats the reason for using prepares at all. You create the SQL using one ? and prepare it and bind it to the one string variable. Then, inside the loop, you just execute it as many times as needed. Try it this way:

$stmt = $conn->prepare("INSERT INTO details (county) VALUES (?)");
$stmt->bind_param("s", $county);

foreach($decoded["data"] as $decode){
      $county = $decode['county'];
      $stmt->execute();
    }

Or, you could make it run without locking it into the an extra variable like this:

$stmt = $conn->prepare("INSERT INTO details (county) VALUES (?)");
$stmt->bind_param("s", $county);

foreach($decoded["data"]["county"] as $county) {
      $stmt->execute();
    }

@ErnieAlex I tried following the solution you posted but both did not seem to work
so i tried this instead

<?php

$servername = "localhost";
$username = "root";
$password = "root";

try {
    $conn = new PDO("mysql:host=$servername;dbname=api-call", $username, $password);
    // set the PDO error mode to exception
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    echo "Connected successfully"; 
}
catch(PDOException $e)
{
    echo "Connection failed: " . $e->getMessage();
}



$ch = curl_init();

$url = "http://example.com/api/properties";

curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$resp = curl_exec($ch);

if($e = curl_error($ch)){
    echo $e;
}
else {
    $decoded = json_decode($resp,true);
    // print_r($decoded);
    foreach($decoded["data"] as $decode){

      $county = $decode['county'];

      $query = 'INSERT INTO details (county) VALUES (:county)';

      $stmt = $conn->prepare($query);

      //Clean Data
      $county = htmlspecialchars(strip_tags($county));

      //Bind data
      $stmt->bindParam(':county', $county);
      // $stmt = $conn->prepare("INSERT INTO details (county) VALUES (?)");
      // $stmt->bind_param("sss", $county);
      
        


      
        

      // //set parameters
      

      $stmt->execute();
      $stmt->close();
      $conn->close();

    }
    
}

curl_close($ch);

Which is only saving one instance of county inside the database instead of all from the API

Again, you are looping and closing your connection. Drop the ->close and ->close. You do not need to close the stmt nor conn… Both are not needed. If you close your statement and re-bind it, it is a total waste of time. And, if you close your connection, then the database is not available. You need to prepare the query and bind it before you loop thru the data… Inside the loop is only the $county= line and the execute line, nothing else. Hope that helps…

@ErnieAlex
I seem to have figured it out but the goal of the task is to make it callable via cli
When i input php index.php in my command line i get this error

test@Test-MacBook-Pro api-call % php index.php
Connection failed: SQLSTATE[HY000] [2002] No such file or directoryPHP Fatal error:  Uncaught Error: Using $this when not in object context in /Users/test/.bitnami/stackman/machines/xampp/volumes/root/htdocs/api-call/index.php:37
Stack trace:
#0 {main}
  thrown in /Users/test/.bitnami/stackman/machines/xampp/volumes/root/htdocs/api-call/index.php on line 37

Fatal error: Uncaught Error: Using $this when not in object context in /Users/test/.bitnami/stackman/machines/xampp/volumes/root/htdocs/api-call/index.php:37
Stack trace:
#0 {main}
  thrown in /Users/test/.bitnami/stackman/machines/xampp/volumes/root/htdocs/api-call/index.php on line 37

How do i achieve this with my current code?

<?php

$servername = "localhost";
$username = "root";
$password = "root";

try {
    $conn = new PDO("mysql:host=$servername;dbname=api-call", $username, $password);
    // set the PDO error mode to exception
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    echo "Connected successfully"; 
}
catch(PDOException $e)
{
    echo "Connection failed: " . $e->getMessage();
}



$ch = curl_init();

$url = "http://example.com/api/properties";

curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$resp = curl_exec($ch);

if($e = curl_error($ch)){
    echo $e;
}
else {
    $decoded = json_decode($resp,true);
    // print_r($decoded);
    $query = 'INSERT 
              INTO 
                  details 
                  (
                    county,
                    country,
                    town,
                    description,
                    displayable_address,
                    image,
                    thumbnail,
                    latitude,
                    longitude,
                    bedrooms,
                    bathrooms,
                    price,
                    -- property_type,
                    type
                  ) 
              VALUES 
                  (
                    :county,
                    :country,
                    :town,
                    :description,
                    :address,
                    :image_full,
                    :image_thumbnail,
                    :latitude,
                    :longitude,
                    :num_bedrooms,
                    :num_bathrooms,
                    :price,
                    -- :property_type.description,
                    :type
                  )
              ';

    $stmt = $conn->prepare($query);

      //Clean Data
      $county = htmlspecialchars(strip_tags($county));

      //Bind data
      $stmt->bindParam(':county', $county);
      $stmt->bindParam(':country', $country);
      $stmt->bindParam(':town', $town);
      $stmt->bindParam(':description', $description);
      $stmt->bindParam(':address', $displayable_address);
      $stmt->bindParam(':image_full', $image);
      $stmt->bindParam(':image_thumbnail', $thumbnail);
      $stmt->bindParam(':latitude', $latitude);
      $stmt->bindParam(':longitude', $longitude);
      $stmt->bindParam(':num_bedrooms', $bedrooms);
      $stmt->bindParam(':num_bathrooms', $bathrooms);
      $stmt->bindParam(':price', $price);
      // $stmt->bindParam(':property_type.description', $property_type);
      $stmt->bindParam(':type', $type);

    foreach($decoded["data"] as $decode){

      $county = $decode['county'];
      $country = $decode['country'];
      $town = $decode['town'];
      $description = $decode['description'];
      $displayable_address = $decode['address'];
      $image = $decode['image_full'];
      $thumbnail = $decode['image_thumbnail'];
      $latitude = $decode['latitude'];
      $longitude = $decode['longitude'];
      $bedrooms = $decode['num_bedrooms'];
      $bathrooms = $decode['num_bathrooms'];
      $price = $decode['price'];
      // $property_type = $decode['property_type']['description'];
      $type = $decode['type'];
      

      
    $stmt->execute();

    }
  1. I have this in my api
    "current_page": 1,
    "data": [
        {
            "uuid": "d8d9c545-3832-3d85-a25a-aac181479be7",
            "property_type_id": "4",
            "county": "Oklahoma",
            "country": "Palm Front",
            "town": "Jigawa",
            "description": "Lorem Ipsum",
            "address": "1 Skitiam Old Apt. 212",

"property_type": {
                "id": 4,
                "title": "Terraced",
                "description": "Lorem Ipsum",
      }
}
]
}          

How do i insert the property_type:description into my database?

$property_type = $decode['data']['property_type']['description'];

You must remember you are using json_decode(…, 1) or json_decode(…,true) which creates an array.
The “property_type” is a sub level of “data” and it contains an array of items. Therefore, you must get the correct entry of correct level of sub-arrays.

As for the error, what does your php logs say the error is. Or tell us what line #37 is or maybe line 36 to line 38…

@ErnieAlex oh yeah that was how i did it but i do not know how to insert it into the database after bindparam (in the previous post i had to comment it out because i could not figure it out)

in regards to the other error and line, here it is below

Connection failed: SQLSTATE[HY000] [2002] No such file or directoryPHP Warning:  Undefined variable $conn in /Users/henrydev/.bitnami/stackman/machines/xampp/volumes/root/htdocs/api-call/index.php on line 78

Warning: Undefined variable $conn in /Users/henrydev/.bitnami/stackman/machines/xampp/volumes/root/htdocs/api-call/index.php on line 78
PHP Fatal error:  Uncaught Error: Call to a member function prepare() on null in /Users/henrydev/.bitnami/stackman/machines/xampp/volumes/root/htdocs/api-call/index.php:78
Stack trace:
#0 {main}
  thrown in /Users/henrydev/.bitnami/stackman/machines/xampp/volumes/root/htdocs/api-call/index.php on line 78

Fatal error: Uncaught Error: Call to a member function prepare() on null in /Users/test/.bitnami/stackman/machines/xampp/volumes/root/htdocs/api-call/index.php:78
Stack trace:
#0 {main}
  thrown in /Users/test/.bitnami/stackman/machines/xampp/volumes/root/htdocs/api-call/index.php on line 78

and here is what is on the line

$stmt = $conn->prepare($query);

So, your data is an array from JSON. So, you use that array and get all the data out of it as needed.
Then, you insert it. But, of course that is a waste of time. You can just bind the data to the json array values. It depends if you need to use the variables you retrieved otherwise in your code. Moving an array of data into separated values just to use them for an insert is a waste of string handling time. Slows everything down a little.

Now, the error is because of several possible problems. It can be caused if you closed the connection string. Meaning $conn->close; … There is never a reason to close your connection. It is never needed. Once you change pages, it is closed from you. It is also closed if you post your page, so why ever close it. Next, it could be that the query was not created correctly. You can dump the $query variable just before you get to that line and see if it is well-formed or not. Either of these can cause that problem.

@ErnieAlex when i dump the $query i got this

string(1074) "INSERT INTO details ( county, country, town, description, displayable_address, image, thumbnail, latitude, longitude, bedrooms, bathrooms, price, type ) VALUES ( :county, :country, :town, :description, :address, :image_full, :image_thumbnail, :latitude, :longitude, :num_bedrooms, :num_bathrooms, :price, :type ) "

Well, it says your $conn string is gone. Did your remove ALL of your ->close lines?
You never need to do that.

@ErnieAlex Exactly what i did is $property_type = $decode['property_type']['description']; but the problem is adding it as VALUE to insert it into the database? and set stmt->bindParams

Does this get the correct value? If so, just BIND the $property_type variable and it will be saved correctly.
Just add this one into your INSERT INTO query bind as property_type and :property_type …

@ErnieAlex Thanks so much it has worked.

Quick question what if i want to store the image on a server, how would i copy this and resize this to a set width/height?

I have an image field in the API

Well, first, congrats on getting it all to work up to this point. Nice going!

Now, images are not very tricky, but, require some thought. I may give you too much info, but, let’s consider all of it so that you can think it out. Designing the image system requires a few things. First, are all the images going to be just JPG or do you have others you want to upload? Often for web pages, PNG is used for the file type. But, otherwise, JPG will work good. Next, are all of these going to be saved on your server in one folder? Normally, you would, but, if the image is linked to one property, you could rename them to the ID of the property. This will not work if you plan to have many different pictures for each property. If only one picture is used, it is easy to rename the picture to the property ID while you resize the image. You would use standard form processing code which will move the picture to the image folder.
For image processing, there are tons of ways to handle that. I suggest using the more standard PHP functions that do this for you. Makes life easy. You use these functions in various ways. Basically, you create a PHP object file from the incoming image. Next you resize it to however you want it. If needed, you convert it into a PNG. Then, you save the resized version. Most likely saving it with a new name that attaches it to the property ID.
Here are some functions you can research or ask us about to solve this next programming puzzle…

$image_object = imagecreatefromjpeg($filename-to-resize);   //  Create an image object from file
$resized_image = imagescale($image_object , 400, 300);     // width: 400 and height: 300
imagejpeg($resized_image, 'images/'.$property_id.'.jpg');       //  Save image as jpeg
imagepng($resized_image, 'images/'.$property_id.'.png');       //  Save image as png

These are just loose examples, but gives you a place to start at. You would need to make sure you know what you want for images, 1 or more per property, know the size you want the images to be set to and also know where you want to store them and the name for them. A few decisions to to make before coding…

Oh, also, here is a beginner’s tutorial on how to handle the uploading of files from a form. It is a basic rundown on all the parts you need to make that work. It’s fairly simple and easy to follow. But, ask away if you get stuck on parts of it. PHP-File-Upload

Hope all this helps!

@ErnieAlex so how would I copy it and save it on the other server ??

Other server? Are you not using a form to upload your data? Use a input field of type file. I posted a like that explains it all. Read the details in PHP-File-Upload link… It should explain it all.

Or, if you are not using a form, you need to use curl to “POST” back to the API. Do you have an API set up to receive files on the other server? Perhaps I am mixed up on your server(s) setups. If you need to use curl, you use a POST routine in curl to send the file to the other server. Or, you can just use FTP in a PHP script to send it if the other server has FTP connections set up for you.

Sponsor our Newsletter | Privacy Policy | Terms of Service