index.php
<!doctype html>
<html ng-app="rjtApp">
<head>
<title>PHP MySQL API Consumed with AngularJS</title>
<script src="angular.min.js"></script>
<script src="data.js"></script>
</head>
<body>
<div ng-controller="GetUsers">
<table>
<thead><tr><th>Name</th></tr></thead>
<tbody>
<tr ng-repeat="user in users"><td>{{ user.name }}</td></tr>
</tbody>
</tfoot></tfoot>
</table>
</div>
</body>
</html>
api.php (this connection has no problem i tested.)
<?php
// set up the connection variables
$db_name = 'air';
$hostname = '127.0.0.1';
$username = 'root';
$password = '123456';
// connect to the database
$dbh = new PDO("mysql:host=$hostname;dbname=$db_name", $username, $password);
// a query get all the records from the users table
$sql = 'SELECT USER_NAME FROM air_users LIMIT 1';
// use prepared statements, even if not strictly required is good practice
$stmt = $dbh->prepare( $sql );
// execute the query
$stmt->execute();
// fetch the results into an array
$result = $stmt->fetch( PDO::FETCH_ASSOC );
// convert to json
$json = json_encode( $result );
// echo the json string
echo $json;
?>
data.js
alert("this is connect");
var app = angular.module("rjtApp", []);
app.controller("GetUsers", function($scope, $http)
{
function getProject(){
$http.get("api.php").success(function(data){
$scope.projects = data; //the data are stored in projects
});
};
});
getProject();
My intention is to make a live validation to check database name exited, but I cannot even figure how to connecting AngularJS to database, what I have been doing wrong?
You are calling getProject from outside the controller, so it is undefined out there (it is local to the controller). So move that call inside:
alert("this is connect");
var app = angular.module("rjtApp", []);
app.controller("GetUsers", function($scope, $http)
{
function getProject() {
$http.get("api.php").success(function(data) {
$scope.projects = data; //the data are stored in projects
});
};
getProject(); // moved this line
});
Then, the $http service should run. Technically, you should be using a GET request, but it will still work the same way with POST. I do want to point out that you are not currently using projects anywhere in your page - so you will only see the data in the network console.
It looks to me like your big issue here is that you are using $http.post instead of $http.get. Post is designed for submitting changes and new objects (think submitting a form), while get is designed for grabbing output.
So, you should be able to change
$http.post("api.php").success(function(data){
$scope.projects = data; //the data are stored in projects
});
to
$http.get("api.php").success(function(data){
$scope.projects = data; //the data are stored in projects
});
This will store the output of loading api.php (as if you visited the website yourself rather than in code) in projects. A useful debug tip is to put
alert(JSON.stringify(varname))
in your code if you wish to debug. This will pop up an alert containing the JSON contents of your variable as a string. In your case this would be:
alert(JSON.stringify($scope.projects)).
I apologize for any code formatting issues. I'm new to the stack overflow system.
Related
I have a web application where I need to get values from a MySQL database.
The series of event is as follows:
PHP code creates HTML page (works fine)
Click a button on the page, updating a cookie (works fine)
Use cookie in a MySQL query (This does not work)
Get a record from the above MySQL query result and pass to HTML page with jQuery
The problem with bullet 3 is that the MySQL query is only run when I load the page (of course). But I need a method to run a query, based on user input (stored as the cookie), without reloading the PHP script.
How can this be done?
My engineering c-coding brain has a really hard time wrapping this ajax thing. Here is the code so far, still not working:
The popup(HTML) I want to update with new strings when a button on the same page, is clicked:
<div id="popup" class="popup" data-popup="popup-1">
<div class="popup-inner">
<h2 id="popup-headline"></h2> //Headline, created from a cookie. Could be "Geography"
<div id="dialog"></div> //From Will's suggestion
<p id="question"></p> //String 1 from online MySQL DB goes here "A question in Geography"
<p id="answer"></p> //String 2 from online MySQL DB goes here "The answer to the question"
<p class="popup-small-button"><a data-popup-close="popup-1" href="#"><br>Close</a></p> // Hides the popup
<a class="popup-close" data-popup-close="popup-1" href="#">x</a>
</div>
</div>
Then i have my file with custom functions. It executes whenever the popup is shown:
<script>
jQuery(function() {
jQuery('[data-popup-open]').on('click', function(e) {
function myfunction(myparams) {
// your logic here: testing myparams for valid submission, etc.
alert("hey");
jQuery.ajax({
type: 'post',
url: 'server.php',
data: {
my_var1: 'question',
my_var2: 'answer'
},
success: function(data) {
data = JSON.parse(data);
jQuery('#question').html(data["question"]);
jQuery('#answer').html(data["answer"]);
},
error: function(jqxhr, status, exception) {
alert('Exception:', exception);
}
});
}
});
});
</script>
My server.php file contains now this:
<?php
require("db.php");
if(isset($_POST['my_var1']) && isset($_POST['my_var2'])) {
myfunction($_POST['my_var1'], $_POST['my_var2']);
}
?>
And my db.php contains this:
<?php
function myfunction($var1, $var2) {
$db = mysqli_connect('MyOnlineSQLPath','username','password','database1_db_dk');
$stmt = $db->prepare("SELECT question, answer FROM t_da_questions WHERE category_id=?;");
$stmt->bind_param("s", $_COOKIE('category'));
$stmt->execute();
$retval = false;
if($result->num_rows > 0) {
$row = $result->fetch_assoc();
if(!is_null($row['question']) && !is_null($row['answer'])) {
$retval = new stdClass();
$retval->question = row['question'];
$retval->answer = row['answer'];
}
}
mysqli_close($db);
return $retval;
}
?>
What I need, is the "question" and "answer" from the SELECT query.
TL;DR I need question and answer strings to go into <p id="question"></p> and <p id="answer"></p> in the HTML, both without refreshing the page. The getCookie('category') is a cookie stored locally - It contains the last chosen category for a question. The function getCookie('category') returns an integer.
Let me know if you need any more info on this.
Here is some template AJAX that may help you out. I used this in another project. This won't require a page refresh. You will have to include the code to send your cookie's data in the 'data' section.
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<meta charset="utf-8">
</head>
<body>
// your HTML here
<script>
<div id="dialog"></div>
function myfunction(myparams) {
// your logic here: testing myparams for valid submission, etc.
$.ajax({
type: 'post',
url: 'myphpfile.php',
data: {
my_var1: 'myval',
my_var2: 'myval2'
},
success: function(data) {
$("#dialog").html("<span>Success!</span>");
$("#dialog").fadeIn(400).delay(800).fadeOut(400);
}
});
}
</script>
</body>
</html>
Then in the file 'myphpfile.php', you'll have code like the following:
<?php
require("../mycodebase.php");
if(isset($_POST['my_var1']) && isset($_POST['my_var2'])) {
myfunction($_POST['my_var1'], $_POST['my_var2']);
}
?>
Finally, in mycodebase.php (which is stored in a place inaccessible to the public/world), you'll have a function that actually runs your query and returns your result:
function myfunction($var1, $var2) {
$db = mysqli_connect('localhost','myuser','mypass','dbname');
$stmt = $db->prepare("UPDATE mytbl SET col1=? WHERE col2=?;");
$stmt->bind_param("ss", $var1, $var2);
$stmt->execute();
$result = (($db->affected_rows) > 0);
mysqli_close($db);
return $result;
}
UPDATE
That function above is to run an UPDATE query, so the result returned just indicates whether you successfully updated your data or not. If you want to return an actual result, you have to extract the result from the query as follows:
function myfunction($cat) {
$db = mysqli_connect('localhost','myuser','mypass','dbname');
$stmt = $db->prepare("SELECT question, answer FROM t_da_questions WHERE category_id=?;");
$stmt->bind_param("s", $cat);
$stmt->execute();
$retval = false;
if($result->num_rows > 0) {
$row = $result->fetch_assoc();
if(!is_null($row['question']) && !is_null($row['answer'])) {
$retval = new stdClass();
$retval->question = row['question'];
$retval->answer = row['answer'];
}
}
mysqli_close($db);
return $retval;
}
Then your server.php file will look like:
<?php
require("db.php");
if(isset($_COOKIE['category'])) {
json_encode(myfunction($_COOKIE['category']));
}
?>
Here's the JS:
jQuery('[data-popup-open]').on('click', function(e) {
function myfunction(myparams) {
// your logic here: testing myparams for valid submission, etc.
alert("hey");
jQuery.ajax({
type: 'post',
url: 'server.php',
// data section not needed (I think), getting it from the cookie
success: function(data) {
data = JSON.parse(data);
jQuery('#question').html(data["question"]);
jQuery('#answer').html(data["answer"]);
}
});
}
});
This is untested -- I may have gotten an argument wrong, but this is at least very close if it's not already there.
I've literally checked out every single ng-repeat question out there but a lot of them don't deal with databases and people just use arrays in JS and a simple $scope.array.push("stuff") works for them.
I've tried $scope.apply, $rootScope and even calling the GET request right after a successful POST request.
I have a form with 2 text inputs, date and content.
When the submit button is pressed, date and content are added into a MySQL database using PHP.
The data is added just fine to the MySQL database and retrieving also works properly.
Even the GET request inside the successful POST request is executed.
So I don't understand why it forces me to refresh the page to see the updated ng-repeat results.
Am I missing something?
Any help or suggestions is greatly appreciated, thanks!
Relevant HTML code
<div ng-controller="insertController">
<h2> What I learned today </h2>
<form>
Date <br>
<input type="text" ng-model="date"><br><br>
Content <br>
<textarea rows="10" cols="50" ng-model="content"></textarea><br><br>
<input type="button" value="Submit" ng-click="insertdata()">
</form>
</div>
<div ng-controller="fetchController">
<span ng-repeat="item in results">
{{item.date}}<br>
{{item.content}}<br><br>
</span>
</div>
insertController.js
var app = angular.module('myApp', []);
app.controller('insertController', function($scope, $http) {
$scope.insertdata = function() {
$http({
method: 'POST',
url: 'http://localhost/storestuff/insert.php',
data: {'date':$scope.date, 'content':$scope.content, 'in':'json-format'},
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})
.then(function(res) {
console.log("Successful response", res)
$scope.date = "";
$scope.content = "";
$http.get('http://localhost/storestuff/fetch.php')
.then(function successCallback(response) {
alert("GOT NEW DATA");
$scope.results = response.data; // Allow angular to access the PHP output data
});
$scope.apply;
})
.catch(function(err) {
console.error("Error with POST", err);
});
}
});
insert.php
<?php
header('Access-Control-Allow-Origin: *');
$theConnection = mysqli_connect("localhost", "root", "", "storestuff");
if(mysqli_connect_errno()) {
echo "Failed to connect to MySQL.";
}
$theData = json_decode(file_get_contents('php://input'));
$date = mysqli_real_escape_string($theConnection, $theData->date);
$content = mysqli_real_escape_string($theConnection, $theData->content);
mysqli_query($theConnection, "INSERT INTO thestuff(date, content) VALUES('$date', '$content')");
mysqli_close($theConnection);
?>
fetchController.js
app.controller('fetchController', function ($scope, $http) {
$http.get('http://localhost/storestuff/fetch.php')
.then(function successCallback(response) {
$scope.results = response.data; // Allow angular to access the PHP output data
});
});
fetch.php
<?php
header('Access-Control-Allow-Origin: *'); // clientside(Node) <-> serverside(PHP)
$mysqli = new mysqli("localhost", "root", "", "storestuff");
if($mysqli->connect_error) {
printf("Connect failed: %s\n", $mysqli->connect_error);
exit();
}
$query = "SELECT * FROM thestuff";
$theData = array();
if($result = $mysqli->query($query)) {
while($row = mysqli_fetch_array($result)) {
$theData[] = array(
'date'=>$row['date'],
'content'=>$row['content']);
}
echo json_encode($theData); // Echo the output for the controller to access
$result->free(); // Free the result set
}
else {
echo "0 results.";
}
$mysqli->close(); // Close the connection
?>
The problem with this code is that you have two different controllers, both with separate scopes. Inserting/updating the $scope.results object/array in one controller, will not update the other $scope; they are separate distinct scopes, both with a copy of the data.
Using two controllers looks correct in your use case. However you should be using a service to access your remote data. Check out this answer for some advice on this https://stackoverflow.com/a/20181543/2603735.
Using a service like in that answer, will allow you to store the array/object of remote data in one place, and reference the SAME object from both controllers. Therefore updating from one controller, will also update the other.
For anyone who will ever stumble on my question, I don't want to just leave my broken code there with no answer but neither can I edit the question and put in my answer cause that would defy the purpose of StackOverflow.
So here is my answer to my own question.
I had to make quite a few changes to what I had before. The biggest change by far, is how I handled the data that was returned by fetch.php.
Instead of just taking the output into $scope.results = response.data;, which would work fine if I wasn't dynamically adding to the database, but for this case, I ended up using a service. (Thanks #jayden-meyer for suggesting Angular services.)
The service allowed me to access the same array from my insertController and from my fetchController instead of having a copy of the same array in both controllers which was my problem.
No changes in the HTML code.
No changes to insert.php.
No changes to fetch.php.
insertController.js
I removed the extraneous GET request I had inside the .then method which was completely unneeded since I can just push to the existing array.
(Thanks #charlietfl for the tip)
Instead I added resultsService.addItem($scope.date, $scope.content); inside of the .then method.
I also added my service as an argument.
app.controller('insertController', function($scope, $http, resultsService) {
result.js
app.service('resultsService', function() {
var results = new Array();
var addItem = function(date, content) {
var obj = new Object();
obj["date"] = date;
obj["content"] = content;
results.push(obj);
}
var getItems = function() {
return results;
}
return {
addItem: addItem,
getItems: getItems
};
});
fetchController.js
var size = 0;
var count = 0;
app.controller('fetchController', function ($scope, $http, resultsService) {
$http.get('http://localhost/storestuff/fetch.php')
.then(function successCallback(response) {
size = (response.data).length;
while(count < size) {
var date = response.data[count].date;
var content = response.data[count].content;
resultsService.addItem(date, content);
count++;
}
size = 0;
count = 0;
$scope.results = resultsService.getItems();
});
});
its been two days since i start to learning about angular js.
its quite fun actually. fyi, im still using static data.
it means nothing when you cant manipulate database rite?
so i jump into the next step. connect it with my db. im using regular php.
if success, i will jump into next step, combining angular and php framework like laravel or codeigniter.
actually, its quit easy to retrieve data from database.
but, im here not to share that story, i found difficulties when trying to input it into database. i dont understand why. the point is i cant get the data from the form in html. im using factory in angular.
here is my add.html :
<h1>add newdata</h1>
new name :
<input type='text' ng-model='newdata.name'> <br>
new city :
<input type='text' ng-model='newdata.city'> <br>
<button ng-click='addData()'>submit</button>
here is my index.html :
//define dependency ngRoute module
var test = angular.module('testPeople', ['ngRoute']);
test.factory('factoryPeople', function($http) {
var factoryPeople= {};
factoryPeople.getPeople = function() {
return $http.get('data.php');
};
factoryPeople.addPeople = function() {
return $http.post('add.php');
};
return factoryPeople;
});
routes :
test.config(function($routeProvider) {
$routeProvider
.when('/add', {
templateUrl : 'add.html',
controller : 'add'
})
.when('/contact', {
templateUrl : 'contact.html'
})
.when('/second', {
templateUrl : 'index2.html'
})
.otherwise({redirectTo: '/'});
});
controller :
test.controller('add', function($scope, $http, factoryPeople){
$scope.tambahData = function() {
//bikin format file json, dari hasil tangkapan form di file add.html
databaru = {
name: $scope.newdata.name,
city: $scope.newdata.city
}
factoryPeople.addPeople(newdata).success(function(result) {
//update data using push method
$scope.listofname.push({
name: $scope.newdata.name,
city: $scope.newdata.city
});
//set form data empty again
$scope.newdata.name= '';
$scope.newdata.city = '';
alert(result);
});
here is my add.php :
<?php
header("Access-Control-Allow-Origin: *");
$host = "localhost";
$user = "root";
$pass = "";
$db = "angular";
$link = mysqli_connect($host, $user, $pass, $db) or die(mysqli_error($link));
// get input data
$data = json_decode(file_get_contents("php://input"));
// take value from array
$name= $data['name'];
$city= $data['city'];
// query insert
$sql = "insert into users (name , city) values ('$name', '$city') ";
// echo message
if(mysqli_query($link, $sql)):
echo"input success| name: $name| city: $city";
else: echo"input failed| name : $name | city: $city";
endif;
?>
if i run that script, data will always succesfully insert into database.
but the problems is $name and $city has no value.
i dont understand why.
am i wrong using php_get_contents or what?
can you guys tell me what should i do in order to get a better result?
Hope you guys can help me.
Thanks a lot.
You forgot to pass the parameters. Change your factory (addPeople() function):
factoryPeople.addPeople = function(data) {
return $http.post('add.php', data);
};
And then just use $_POST on the server like you usually (I guess) do
I wanted to know if something like the following would be fairly secure and okay to use in a production setting. I am retrieving data from a database and using the response data into a graph using Chart.js.
My html file
<div id="canvas-holder">
<canvas id="chart-area2" width="200" height="200" />
</div>
<div id="canvas-holder">
<canvas id="chart-area" width="200" height="200" />
</div>
<div id="chartjs-tooltip"></div>
<script>
$.ajax({
url: 'chartpi.php',
success: function (response) {//response is value returned from php
var datachart = JSON.parse(response);
var ctx2 = document.getElementById("chart-area2").getContext("2d");
window.myPie = new Chart(ctx2).Pie(datachart);
}
});
$.ajax({
url: 'chartpi2.php',
success: function (response) {//response is value returned from php
var datachart = JSON.parse(response);
var ctx = document.getElementById("chart-area").getContext("2d");
window.myPie = new Chart(ctx).Doughnut(datachart);
}
});
</script>
My PHP file
<?php
// set up the connection variables
$db_name = '$dbname';
$hostname = '$host';
$username = '$uname';
$password = '$pass';
// connect to the database
$dbh = new PDO("mysql:host=$hostname;dbname=$db_name", $username, $password);
// a query get all the records from the users table
$sql = 'SELECT * FROM pichart2';
// use prepared statements, even if not strictly required is good practice
$stmt = $dbh->prepare( $sql );
// execute the query
$stmt->execute();
// fetch the results into an array
$result = $stmt->fetchAll( PDO::FETCH_ASSOC );
// convert to json
$json = json_encode( $result );
// echo the json string
echo $json;
?>
Your question of
would be fairly secure and okay to use in a production setting
The two obvious area's you have covered
parameterized queries on the backend
the data being retrieved is not based on user input from this site page
However, I will caution that if any of the data being retrieved from the piechart table(s) retains any user provided data from some other source, that you should consider/implement the proper output encoding even if proper input sanitation was performed.
If that isn't the case, then no worry there.
I'm writing a webapp which successfully allows me to login to Facebook (I'm using Phonegap and the Phonegap Facebook plugin). I then want to store the logged in users name and ID. To start with as a simple test I wanted to get the following controller to run collect the ID, display it in the xcode console to confirm it was there and then send it to the php code below to then store in a mysql table. I can't seem to get it working and I think it's possibly the format of my data in the {}'s within the $http.post but it's a bit beyond my current knowledge to figure this one out. Any ideas?
function FacebookCtrl($scope) {
FB.api('/me', function(response) {
var fbid=response.id;
console.log('Testing, ' + fbid + '.');
$http.post('http://somedomain.co.uk/php/users.php', {uid: fbid})
console.log('Complete');
});
}
The php code at the receiving end is:
<?php
$data = file_get_contents("php://input");
$objData = json_decode($data);
$uid = $objData->uid;
try {
include 'database.php';
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $conn->prepare('INSERT INTO Userdata (oauth_uid) VALUES (:userid)');
$stmt->execute(array(
':userid' => $uid,
));
} catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
}
?>
The same php code works with another one of my controllers however the difference is that the other controller captures the data passed from a form so the http.post looks like this:
$http.post('http://somedomain.co.uk/php/submitdata.php', {Position1: $scope.position1}
And the code in the php that captures this data is:
$Position1 = $objData->Position1->Name;
As the code all works on another controller, I'm assuming that the issue is with how I'm formatting the data I'm passing between the {}'s?
Try to define success \ error callbacks
$http.post("http://somedomain.co.uk/php/users.php", {uid: fbid})
.success(function(data, status, headers, config) {
$scope.data = data;
}).error(function(data, status, headers, config) {
$scope.status = status;
});
What will it say then?