How can I configure Flutter to use two different APIs? - flutter

I have a Flutter app and I would like to call multiple API endpoints which use different databases.
I don't know if I should do this on the backend or the frontend.
api1.php:
<?php // header('Content-Type: application/json');
include "config.php";$sql = "select inventeries.pic_inv,inventeries.name,site.Sname,users.number from inventeries,site,users";
$stmt = $con->prepare($sql);
$stmt->execute();
$med = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode($med);
?>
api_2.php:
<?php
// header('Content-Type: application/json');
include "config.php";
$sql = "select users.pic_inv,users.name,site.Sname,users.number from users,site,users";
$stmt = $con->prepare($sql);
$stmt->execute();
$med = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode($med);
?>
Currently they use the same database, so the results from both APIs are the same:
{"pic_inv":"ACICAL-PLUS.jpg","name":"Aclcal","Sname":"flowers pharma","number":"7894561231"}
{"pic_inv":"ACICAL-PLUS.jpg","name":"Aclcal","Sname":"flowers pharma","number":"123456789"}
{"pic_inv":"what-a-treatment-for-migraine-headache.jpg","name":"foar","Sname":"flowers pharma","number":"7894561231"}
{"pic_inv":"what-a-treatment-for-migraine-headache.jpg","name":"foar","Sname":"flowers pharma","number":"123456789"}
{"pic_inv":"syrunj.png","name":"AMLO","Sname":"flowers pharma","number":"7894561231"}
{"pic_inv":"syrunj.png","name":"AMLO","Sname":"flowers pharma","number":"123456789"}
{"pic_inv":"cap.jpg","name":"pandol","Sname":"flowers pharma","number":"7894561231"}
{"pic_inv":"cap.jpg","name":"pandol","Sname":"flowers pharma","number":"123456789"}

Well, as i have said, i have no experience with PHP and all would be easier in the API..
but you can make a model in your flutter app like lets say the data you get from DB1 endpoint is like this
{
"inventeries.pic_inv" : "something",
"inventeries.name" : "something",
"site.Sname" : "something",
"users.number" : "something"
}
and the data you get from DB2 Endpoint is like this
{
"users.pic_inv" : "something",
"users.name" : "something",
"site.Sname" : "something",
"users.number" : "something"
}
then you prepare a model that combines all to be something like this.. lets call it MixedModel
{
//Mixed both data and get only the data you want..
"users.pic_inv" : "something",
"users.name" : "something",
"inventeries.pic_inv" : "something",
"inventeries.name" : "something"
"site.Sname" : "something",
"users.number" : "something",
}
you can use https://app.quicktype.io/ to generate the models for your data.
then you can make a function that can make a call to both of the endpoints
im using Dio Package to make the API Calls..
Future<List<MixedModel>> GetDataFromADatabase() async {
try{
String URL_ENDPOINT_ONE = "URL TO ENDPOINT 1";
String URL_ENDPOINT_TWO = "URL TO ENDPOINT 2";
var ResponseOne = await Dio().get(URL_ENDPOINT_ONE);
var ResponseTwo = await Dio().get(URL_ENDPOINT_TWO);
if(ResponseOne.statusCode == 200 && ResponseTwo.statusCode == 200){
// only if both requests are successful
var data = jsonDecode(ResponseOne.data.toString()) as List<MixedModel>;
//combine data
data.addAll(json.decode(ResponseTwo.data.toString()) as List<MixedModel>);
return data;
}
List<MixedModel> empty = [];
return empty;
}
catch (ex){
List<MixedModel> empty = [];
if(ex is dio.DioError){
print( ex.response);
}
return empty;
}
}
I hope you get the idea

Related

The data i get back to FETCH from my PHP file, had an added empty paragraph at the beginning

I use the FETCH API to pull data from the backend, but since some time I am getting an empty paragraph at the beginning of each response. Unfortunately for me, I am not able to track down what change was made that has caused this, so I am looking for possible reasons why this would happen in order to eliminate it.
Below is once such fetch:
await fetch('__transport.php', {
method: "POST",
body: new URLSearchParams("pk="+pk+"&drvr="+drvr+"&col="+col)
})
.then(response => response.text())
.then((response) => {
if(response.substr(0,6) == "Failed") {
alert(response)
} else {
document.getElementById(id).innerHTML = response;
}
})
.catch(err => console.log('s/g went wrong', err));
and here the backend, the mysql query was removed from the end, but it returns a name
$pk = $_POST['pk'];
$drvr = ($_POST['drvr'] != 0 ? $_POST['drvr']:'NULL');
$col = $_POST['col'];
$sql = "UPDATE mytable
SET
$col = $drvr
WHERE pkcolumn = $pk";
if ($conn->Execute($sql)==false) {
exit("Failed to update database\n\n".$conn->ErrorMsg()."\n\n".$sql);
} else if($drvr != 'NULL'){
//mysql query removed for simplification as I get the same result with this
$name = "Jack Sparrow";
exit($name); //returns the name to the above FETCH
} else {
exit(' '); //returns no name as the field should be blank in this case
}
I am expecting the return "Jack Sparrow" to be received by the JavaScript in the variable "response", as:
"Jack Sparrow"
What I get is and empty paragraph followed by the name:
"
Jack Sparrow"

Update embedded subdocument in array with doctrine and mongodb

I want to update (replace) a subdocument within an array of all the documents, that have this specific embedded subdocument.
My sample content object is:
{
"_id" : ObjectId("51f289e5345f9d10090022ef"),
"title" : "This is a content",
"descriptors" : [
{
"_id" : ObjectId("51f289e5345f9d10090022f4"),
"name" : "This is a descriptor",
"type" : "This is a property"
},
{
"_id" : ObjectId("51f289e5345f9d10090022f0"),
"name" : "This is another descriptor",
"type" : "This is another property"
}
]
}
I want to find the object with a specific descriptor._id.
I want to replace the one subdocument with another one (respectivley with an updated version of the old object, but not necessarily with the same properties).
While this works well in RoboMongo / shell...
db.Content.update(
{
'descriptors._id': ObjectId("51f289e5345f9d10090022f4")
},
{
$set: {
'descriptors.$': {
"_id" : ObjectId("51f289e5345f9d10090022f4"),
"name" : "This is the updated descriptor",
"category" : "This is a new property"
}
}
},
{
'multi': true
})
...and with the plain php methods...
$descriptor = array();
$descriptor['_id'] = new \MongoID('51f289e5345f9d10090022f4');
$descriptor['name'] = 'This is the updated descriptor';
$descriptor['category'] = 'This is a new property';
$mongo = new \Mongo('mongodb://localhost:27017');
$database = $mongo->selectDB('MyDatabase');
$output = $database->selectCollection('Content')->update(
array('descriptors._id' => $descriptor['_id']),
array('$set' => array('descriptors.$' => $descriptor)),
array("multiple" => true)
);
...it doesn't work with Doctrine MongoDB ODM...
$descriptor = array();
$descriptor['_id'] = new \MongoID('51f289e5345f9d10090022f4');
$descriptor['name'] = 'This is the updated descriptor';
$descriptor['category'] = 'This is a new property';
$query = $dm->createQueryBuilder('Content')
->update()->multiple(true)
->field('descriptors._id')->equals($descriptor['_id'])
->field('descriptors.$')->set($descriptor)
->getQuery()->execute();
...because it fails with the following error:
Notice: Undefined offset: 2 in C:\MyProject\vendor\doctrine\mongodb-odm\lib\Doctrine\ODM\MongoDB\Persisters\DocumentPersister.php line 998
So I assume, that Doctrine MongoDB ODM needs three parts in the dot-notation. The not so nice solution would be to iterate over the properties of the subdocument and set them manually.
$descriptor = array();
$descriptor['_id'] = new \MongoID('51f289e5345f9d10090022f4');
$descriptor['name'] = 'This is the updated descriptor';
$descriptor['category'] = 'This is a new property';
$query = $dm->createQueryBuilder('Content')
->update()->multiple(true)
->field('descriptors._id')->equals($descriptor['_id']);
foreach ($descriptor as $key => $value) {
$query->field('descriptors.$.'.$key)->set($value);
}
$query->getQuery()->execute();
But this will only update existing and add new properties, but won't remove old/unnecessary properties from the subdocument.
Any ideas how to solve the problem:
with a simple query
while using Doctrine MongoDB ODM
without looping over the subdocument-array in php
I'm using:
Mongo-Server: 2.4.5
PHP: 5.4.16
PHP-Mongo-Driver: 1.4.1
Composer:
"php": ">=5.3.3",
"symfony/symfony": "2.3.*",
"doctrine/orm": ">=2.2.3,<2.4-dev",
"doctrine/doctrine-bundle": "1.2.*",
"doctrine/mongodb-odm": "1.0.*#dev",
"doctrine/mongodb-odm-bundle": "3.0.*#dev"
This was a bug in ODM and should be fixed in PR #661. Please take a look and ensure that the revised test satisfies your use case.
Until the next beta of ODM is tagged, this will only reside in the master branch; however, that should match your 1.0.*#dev version requirement.
You can do this thing but in a "not easy" way becuse when you use EmbedMany or ReferenceMany in Doctrine becames a Doctrine ArrayCollection objects that implemented the ArrayCollection contains() method with (as explained here) with the PHP in_array() method with the $strict parameter set to true... this way works with ReferenceMany but not with EmbedMany!
The concept is: ArrayCollection -> array -> ArrayCollection
In the definition of Document
...
/**
* #ODM\EmbedMany(targetDocument="EmbeddedElement")
*/
private $elements = array();
...
public function getElements() { return $this->elements; }
public function setElements($elements) { $this->elements = $elements; }
public function addElement(Element $element) { $this->elements[] = $element; }
public function setElement(Element $element, $index=0)
{
$elementsArray = $this->elements->toArray();
$elementsArray[$index] = $element;
$this->elements = new ArrayCollection($elementsArray);
}
public function removeElement(Element $element)
{
$index = array_search($element, $this->elements->toArray(), $strict=false);
if($index !== false)
$this->elements->remove($index);
}
public function removeElementByIndex($index) { $this->elements->remove($index); }

Image capture/upload with Phonegap (cordova) for iPhone not working

I have been trying to set up an app through PhoneGap (Cordova) to take images and upload them to our server. I have gone through so many of the responses on here and tried the code in them. I can get the camera up and taking a photo, I can access the phone gallery even. But I can not get it to send the image to the server. I've tried sending the image, and even sending the base64 image stream. I can't get it to the server.
Here is the javascript on the client side:
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
}
function ImageUpload() {
this.useExistingPhoto = function(e) {
this.capture(Camera.PictureSourceType.SAVEDPHOTOALBUM);
}
this.takePhoto = function(e) {
this.capture(Camera.PictureSourceType.CAMERA);
}
this.capture = function(sourceType) {
navigator.camera.getPicture(this.onCaptureSuccess, this.onCaptureFaile, {
destinationType: Camera.DestinationType.FILE_URI,
soureType: sourceType,
correctOrientation: true
});
}
this.onCaptureSuccess = function(imageURI) {
var fail, ft, options, params, win;
success = function(response) {
alert("Your photo has been uploaded!");
};
fail = function(error) {
alert("An error has occurred: Code = " + error.code + "\nMessage = "+error.message);
};
options = new FailUploadOptions();
options.fileKey = "file";
options.fileName = imageURI.substr(imageURI.lastIndexOf('/') + 1);
options.mimeType = "text/plain";
params = {
val1: "some value",
val2: "some other value"
};
options.params = params;
ft= new FileTransfer();
ft.upload(imageURI, 'http://style.appdev01.com/app/client-profile.php', success, faile, options);
}
this.OnCaptureFail = function(message) {
alert("Failed because: "+message);
}
};
var imageuploader = new ImageUpload();
Two buttons call imageuploader.takePhoto and .useExistingPhoto on click.
On the server side I have this php:
if(isset($_FILES['file'])) {
$target_path = "/home/style/public_html/images/client_images/app_image.jpg";
move_uploaded_file($_FILES['file']['tmp_name'], $target_path);
$insert = "INSERT INTO
`fut`
SET
`request` = '".serialize($_POST)."',
`file` = '".serialize($_FILES)."'";
$mysql->query($insert);
}
This is just to store the POST and FILE arrays to the db to make sure they came through and create the image.
But again, nothing is getting to the server. Any help would be GREATLY appreciated. I've tried so many versions of this code from so many questions here and all over the web.
define ('SITE_ROOT', realpath(dirname(__FILE__))); /* echo SITE_ROOT; to dir
move_uploaded_file($_FILES["file"]["tmp_name"],SITE_ROOT."/uploads/".$_FILES["file"]["name"]); // will move file, make sure uplaods has write permission!
That works for me on Android Simulator, not on Tablet, but let me know if you have it working, busy on the same thing.
$myarray = array( $_REQUEST);
foreach ($myarray as $key => $value) {
echo "<p>".$key."</p>";
echo "<p>".$value."</p>";
echo "<hr />";
}
That you can use to check POST / GET!
Try this is my code. It has worked for me.
Encode your URL by encodeURI method
fileKey with "file" as in your server side script $_FILES['file']
uploadFile: function(refNo){
var uri = fileUpload.fileUri;
var file = uri.substr(uri.lastIndexOf('/') + 1);
var options = new FileUploadOptions();
options.fileKey = "file";
options.fileName = file;
options.mimeType="image/jpeg";
alert("name === "+uri);
options.chunkedMode = false;
var ft = new FileTransfer();
Common.ajaxLoading('show');
ft.upload(uri,encodeURI("http://172.16.1.147:80/upload/home.php") , fileUpload.uploadSuccess, fileUpload.uploadFail, options, true);
},

How to migrate mysqli to pdo

Hi I was wondering how I would migrate a mysqli php file to use PDO. Would anyone be able to take a look at my code and see if I'm on the right track?
This is my original (mysqli) code:
<?php
// connecting to database
$conn = new mysqli('xxxxxx', 'xxxxxx', 'password', 'xxxxxx');
$match_email = 'email';
$match_passhash = 'passhash';
if (isset($_POST['email'])) {
$clean_email = mysqli_real_escape_string($conn, $_POST['email']);
$match_email = $clean_email;
}
if (isset($_POST['passhash'])) {
$clean_passhash = mysqli_real_escape_string($conn, $_POST['passhash']);
$match_passhash = sha1($clean_passhash);
}
$userquery = "SELECT email, passhash, userlevel, confirmed, blocked FROM useraccounts
WHERE email = '$match_email' AND passhash = '$match_passhash'
AND userlevel='user' AND confirmed='true' AND blocked='false';";
$userresult = $conn->query($userquery);
if ($userresult->num_rows == 1) {
$_SESSION['authorisation'] = 'knownuser';
header("Location: userhome.php");
exit;
} else {
$_SESSION['authorisation'] = 'unknownuser';
header("Location: userlogin.php");
exit;
}
?>
And this is my attempt to migrate it to PDO:
<?php
// connecting to database
$dbh = new PDO("mysql:host=xxxxxx; dbname=xxxxxx", "xxxxxx", "password");
$match_email = 'email';
$match_passhash = 'passhash';
if (isset($_POST['email'])) {
$clean_email = mysqli_real_escape_string($conn, $_POST['email']);
$match_email = $clean_email;
}
if (isset($_POST['passhash'])) {
$clean_passhash = mysqli_real_escape_string($conn, $_POST['passhash']);
$match_passhash = sha1($clean_passhash);
}
$userquery = "SELECT email, passhash, userlevel, confirmed, blocked FROM useraccounts
WHERE email = ':match_email' AND passhash = ':match_passhash' AND
userlevel='user' AND confirmed='true' AND blocked='false';";
$stmt = $dbh->prepare($query);
$stmt->bindParam(":match_email", $match_email);
$stmt->bindParam(":match_passhash", $match_passhash);
$stmt->execute();
$userresult = $conn->query($userquery);
if ($userresult->num_rows == 1) {
$_SESSION['authorisation'] = 'knownuser';
header("Location: userhome.php");
exit;
} else {
$_SESSION['authorisation'] = 'unknownuser';
header("Location: userlogin.php");
exit;
}
?>
I'm also not sure how to count the number of rows returned in PDO.
If anyone would be able to help me out that wold be very great.
A million thanks in advance!
When using prepared statements and $stmt->bindValue() or $stmt->bindParam() you do not need to escape values with mysqli_real_escape_string(), PDO will do that for you.
Just remember to set a correct data type for the value. That is the third argument in the bind functions and it is a string by default so your code here is fine. I would only use bindValue() instead of bindParam() as you do not need references.
$stmt->execute() will run your prepared statement as a query. The other $conn->query() does not work with prepared statements. It is for raw queries, like you used to have with MySQLi.
When $stmt->execute() runs your response is saved in the $stmt object. For row count use $stmt->rowCount().

How to get the facebook app_access_token?

I want to create a score for my Facebook app and I know you need an app_access_token for that. Some posts say, the only way to get an app_access_token is via PHP, like this:
<?php
$APPLICATION_ID = YOUR_APP_ID;
$APPLICATION_SECRET = YOUR_APP_SECRET;
$token_url = "https://graph.facebook.com/oauth/access_token?" .
"client_id=" . $APPLICATION_ID .
"&client_secret=" . $APPLICATION_SECRET .
"&grant_type=client_credentials";
$app_token = file_get_contents($token_url);
?>
Is the token you get via this PHP script different from the so called "app token" you find on
https://developers.facebook.com/tools/access_token/?
(looks like this: APPLICATION_ID|lvATVyhp1m.............w)
and is acually the same you get by calling
https://graph.facebook.com/oauth/access_token?client_id=CLIENT_ID&client_secret=CLIENT_SECRET&grant_type=client_credentials directly.
So why must this call be made via PHP?
You can get token by various ways
<a href='https://www.facebook.com/dialog/oauth?client_id=2926561407xxxxx&redirect_uri=http://localhost:8080/fb/getCode.html&rcount=1&scope=email,read_stream'>Login</a>
It will return the token through URL you can get it by:
function getURLParameters(access_token)
{
var sURL = window.document.URL.toString();
if (sURL.indexOf("?") > 0)
{
var arrParams = sURL.split("?");
var arrURLParams = arrParams[1].split("&");
var arrParamNames = new Array(arrURLParams.length);
var arrParamValues = new Array(arrURLParams.length);
var i = 0;
for (i=0;i<arrURLParams.length;i++)
{
var sParam = arrURLParams[i].split("=");
arrParamNames[i] = sParam[0];
if (sParam[1] != "")
arrParamValues[i] = unescape(sParam[1]);
else
arrParamValues[i] = "No Value";
}
for (i=0;i<arrURLParams.length;i++)
{
if(arrParamNames[i] == "code")
{
code = arrParamValues[i];
return arrParamValues[i];
}
}
return "No Parameters Found";
}
}
getURLParameters();