How does codeigniter MVC work with AJAX?
More specifically, what is the most basic AJAX functionality that allows one to send data to a model, then back to a view? Could you explain the majority of the components involved in depth?
As a newbie to PHP/JS/Codeigniter and web development in general, understanding the concepts behind AJAX and how it connects with codeigniter was one of the more confusing things to wrap my head around.
The majority of answers on SO and other tutorial sites seemed to come from the viewpoint of someone very experienced, where it didn't make much sense to the laymen.
As such, I've decided to do a very 'basic' answer that should hopefully help most newcomers who are trying to understand how and why this code works. Keep in mind, that this is supposed to be a very basic explanation. Feel free to edit, but try to keep it simple and without jargon.
I'm not going to get into the details regarding definitions, as you can do that through google. I'll start with the first step, the javascript.
On your page, you'll want to find a spot for the actual AJAX. Be sure to have JQUERY loaded. for more information on that, Google 'Jquery', and load the library ASAP.
For this scenario, we'll add our script directly into the HTML, because its easier. Alternatively, you could load an external JS script similarly to how you load stylesheets.
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<meta property="og:image" content="<?php echo base_url()?>img/logo/logo-big.jpg"/>
<!--[if lt IE 10]>You are living in the past...Upgrade you Browser!! OMFG (google chrome/fire fox)<![endif]-->
<html lang="en">
<head>
<script src="/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript" src="1.8.21/jquery-ui.min.js"></script>
<link href="<?php echo base_url()?>css/account.css" rel="stylesheet" type="text/css"
</head>
<body>
<div class="ajaxContainer">
<form id="ajaxForm" method="get">
<input type="text" id="ajax_input" name="q" placeholder="Type Here"/>
<input type="submit" id="ajax_submit" value="" />
</form>
</div>
</body>
Inside the HTML, add the following script (anywhere, though I usually add it at the top):
<script>
$('.ajaxContainer').delegate('#ajaxForm', 'submit', function() {
$.ajax({
var submitdata = $('#ajax_input').val();
type: "POST",
url: '/ajax/getdata',
dataType: 'json',
data: { submitdata: submitdata },
success: function(data){
$('#ajax').html(data['content']);
}
});
return false;
});
</script>
As for the explanation:
1 $('.ajaxContainer').delegate('#ajaxForm', 'submit', function() {
I used jqueries delegate function to pick up the submit click. Simple enough. It scans all ids/classes within the specified div/class (.ajaxContainer).
2 $.ajax({
This is where the magic starts.
3 var submitdata = $('#ajax_input').val();
Here you will simply 'grab' the data that you want to use in your controller/model. This isn't necessary, but it certainly helps for this explanation. Here, we are taking the value inside #ajax_input and adding it to the javascript variable submitdata for use later on.
4 type: "POST",
Hopefully you are familiar with post/get and typical html form submission. In this example, we specify POST for how we will submit the data. You can change to GET if you want to. Play around with it.
Notice how each section is separated by a , Not overly complicated, just something to take note of. In fact, there are many other things you can add to this code. Take a look at jquery AJAX documentation for more info and play around. http://api.jquery.com/jQuery.ajax/
5 url: '/ajax/getdata,
This is the controller you are calling. I'll explain more later, however, you want to create and ajax controller and a function inside it named getdata. Again, youre simply pointing ajax to a URL. In theory, you could access the page manually by typing it in the address bar. Once you pass the data to that controller, you are working with PHP/codeigniter, and one step closer to successfully performing an AJAX call.
6
dataType: 'json',
data: { submitdata: submitdata },
Specify what type of data you expect to be returned with dataType.
data: sends POSTED data to your controller to be picked up and used in your model. the first submitdata: is the variable we made earlier, and the second represents the name you will be searching for in your controller.
At this point, we will move over to the controller. If you recall, we directed our AJAX call to the url: - /ajax/getdata,
I alluded to creating a controller/function that mirrored that URL. Heres what it would look like:
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
class Ajax extends CI_Controller
{
function __construct()
{
parent::__construct();
$this->load->model('logic_model');
}
public function getdata()
{
//First, grab the data being passed via AJAX through post
$submitteddata = $this->input->post('submitdata');
//Then send that data to your model to do whatever you want.
$data['content'] = $this->logic_model->dosomething($submitteddata);
// you need to echo the data. json_encode turns an array into a JSON formatted string. Without this, you will not receive a success, and you lose sir, goodday.
echo json_encode($data);
}
}
And our Model, aka: logic_model ->
public function dosomething(submitteddata)
{
return "Success!"
}
It returns Success! without will feed back into the controller, $data['content'] and then will be echoed.
We now return to javascript where it checks everything that happened and performs either the success: or failure: function (read documentation for more on failure).
7
success: function(data){
alert(data['content']);
}
As you can see, the function includes the parameter, data This represents the JSON we echoed in the ajax controller. It works just like an array. If successful, it should alert the returned string 'Success!"
And its THAT simple. Obviously, as your task changes, so do a few of the steps, but it will typically just expand on the above scenario.
Hopefully people find this helpful coming from someone who isn't that adept at PHP/AJAX yet, but has come a long way.
Related
I have a .php file with HTML code and inside it I call another php with html file with AJAX. A form.
Apparently something with this form is wrong, or the query after it. Problem is:
When I submit it, the page reloads, and I cannot debug my form.
When I use preventDefault on my code, and prevent the form from
submitting I cannot debug because the query is not executed yet.
Cannot write an html message displaying the variable because after
reload php with the form is gone.
How can I debug my code in this situation?
File1.php
$(".edit-post").click(function(){
var postid = $(this).attr("id");
$.ajax({
type: "GET",
url: "/admin/EditProductForm.php/",
dataType: "html",
data: {
ajaxpostid: postid
},
success: function(data){
$('#post').html(data);
}
});
$("#post").show();
});
EditProductForm.php
<?php
$ID = $_GET["ajaxpostid"];
$post = GetProduct($ID);
if(!empty($_POST)){
...query
}
?>
<html>
<form>
.
.
.
</form>
</html>
The first thing to understand is that although your HTML and Javascript might have been delivered to the workstation by PHP, it is now running in a totally separate environment with no access to PHP at all.
The PHP you're running on your server is running in the server environment, and has no access to the HTML and JavaScript running in the browser.
The two parts of your application communicate either by sending data as part of a GET or POST request when the form is submitted, or by sending and receiving messages through AJAX. It would be unusual to use both methods in one page.
Thus, you can debug the two parts separately.
Turning to your code:
Your AJAX code is triggered when your button is clicked. In the absence of any other attributes, the button will also trigger a submit. This is what is causing the page to reload. Since you're using AJAX to update your page you don't want it to reload, so stop it with preventDefault();
$(".edit-post").click(function(event){ // add the event parameter here
event.preventDefault(); // Prevent the default action - the submit.
var postid = $(this).attr("id");
...
With this done you can use the browsers tools Network tab to watch the messages, see what's being sent, and look at what response is received.
The server end of things is a little more awkward, but adding echo statements at appropriate places can provide useful output while debugging. Note that you don't need your AJAX script to debug the server end - a simple HTML form with the right fields will do. If you're using GET you could even type the URL and query string on the command line by hand and watch the results.
In your code there is a basic flaw, however.
In your AJAX code you're setting the request type to GET (type: "GET",). In your PHP script you're looking for $_GET["ajaxpostid"];, which is OK, but then you start looking at the $_POST array, which will be empty because your AJAX call used GET.
Now at this point, there's not enough code to be clear about what you're trying to achieve. If your SQL query is just retrieving data to populate an edit form then GET is an appropriate method, and you shouldn't be looking at the $_POST` array.
However, the code you've posted suggests that the EditProductForm.php code is generating the HTML to perform the edit. If this is the case you don't need AJAX at all, and you can just submit the form from File1.php. On the other hand, if you want the page to transform to an editing form without a refresh then File1.php needs to create the editing form and incorporate the data sent by the server, and your EditProductForm.php should not do that job.
a button on form can have three types button|submit|reset , the default type is submit.
on your case, you are clicking on button which has the default type of submit, so its submitting form. that's why the page refreshes. but you want to apply Javascript instead.
so in these cases, either you apply event.preventDefault(); with the javascript code to stop form submission, or simply add type="button" to your button to explicitly say this button is going to run javascript
type=submit -> it means button is going to submit form date
type=reset -> it means button is going to clear form data
type=button -> it means button is going to apply javascript
<button type="button">Submit</button>
file 1(jquery):
$(".edit-post").click(function(){
var postid = $(this).attr("id");
$.ajax({
type: "GET",
url: "./EditProductForm.php",
dataType: "html",
data: {
ajaxpostid: postid
},
success: function(data){
$('#post').html(data);
}
});
$("#post").show();
});
file 2:
<?php
if($_GET["ajaxpostid"] == "test"){
?>
<!DOCTYPE html>
<html lang="fa">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type='text/css' href="../Requirement/css/bootstrap.min.css">
<link rel="stylesheet" type='text/css' href="./index.css">
<title>test</title>
</head>
<body>
<h1>hello world !</h1>
<script src="../Requirement/js/jquery-3.5.1.min.js"></script>
<script src="../Requirement/js/bootstrap.min.js"></script>
<script src="../Requirement/hls.js/dist/hls.min.js"></script>
</body>
</html>
<?php } ?>
So here I am posting my first PHP function that I am proud of but I just recently learned about AJAX and wanted to test it out. Unfortunately I can't get it to work.
My experience: PHP (3 weeks). CSS3, HTML, Basic Javascript.
My Problem: Getting AJAX to work. I want ajax to get my data from the php file which gets the votes from my test server (Xampp) database. So each time the user clicks on good or bad AJAX should display the new results without refreshing the page. The issue is however that: A) My if statements work by checking isset($_POST) which wont work anymore if I call by AJAX. B) Preventing refresh. C) Making AJAX update after every click. I know im nearly there, im just missing something and I dont know exactly what it is to be honest.
What I tried: Checked my database connection. Checked if my php code worked without ajax and it does perfectly fine (I am just displaying half of the functionality here, a lite version, for the sake of simplicity). Tried to change submit to button. Cache clearing. Jquery is in the head of my document and the path is correct. Watched tutorials and read the documentation but I am just not heading anywhere, probably due to lack of experience.
Edit: Sessions and everything php works fine. I my session start and database connection are included on the very top.
Summary: How do I fix this ajax so that it always updates my numbers?
Let me know if you want me to explain parts of my php code. Im willing to comment the parts if neccesary.
JQUERY / AJAX CODE
function vote() {
var request = $.ajax({
url: "php/core/voting_system.php",
type: "POST",
dataType: 'html'
});
request.done(function(vote_sum) {
$("#votes").html(vote_sum);
});
}
HTML CODE:
<div id='votes'></div>
<form id="good" action="" method="post">
<input type="submit" name="good" onclick="vote()" value="+">
</form>
<form id="bad" action="" method="post">
<input type="submit" name="bad" onclick="vote()" value="-">
</form>
In HTML you don't need <form>, you are doing it with AJAX, right?
<div id='votes'></div>
<button onclick="vote('good');">+</button>
<button onclick="vote('bad');">-</button>
In JavaScript, it is easier to use post rather than ajax function
function vote(gb) {
$.post("php/core/voting_system.php", { vote: gb }, function(vote_sum) {
$("#votes").html(vote_sum);
});
}
In PHP, extract the vote and use it as needed (add validation/sanitation):
$vote = $_POST['vote']; // either 'good', or 'bad'
// do what you need with it
TL;DR version:
You didn't include a data field inside your $.ajax call. Also, your script isn't checking which button was pressed.
The long version
When you're performing your $.ajax call, you fail to attach any data to the request. This can be done easily like so:
$.ajax({
method: 'POST',
dataType: 'json',
data: ...someJSONData...
});
Usually, you're going to want to pass JSON to anything, because it can contain complex object structures that you would usually want to communicate between the client and the server. You're clearly not in this example, but if you're trying to learn this stuff, it's better to start off the right way.
Both javascript and php make using the JSON format extremely easy: JS JSON.stringify() and JSON.parse(), PHP json_encode() and json_decode().
function vote(e) {
// e.target.id stores the id of the button that was clicked
var data = {vote: e.target.id}
$.ajax({
method: 'POST',
dataType: 'json',
data: JSON.stringify(data),
... callbacks and other properties ...
});
}
document.getElementById("good").addEventListener("click", vote);
document.getElementById("bad").addEventListener("click", vote);
This would be a simple example of how you could solve your problem. If you did a simple var_dump in your php script after running the data through json_decode() you would get a nice associative array:
[
'data' => 'good',
]
I hope this illustrates how easy it is to pass data around in this format.
Also notice I defined the event handlers in the javascript. This is generally better, because you keep all your javascript in one place and it makes things cleaner and easier to debug.
Like Jay said you're not sending POST data through the AJAX. You also need to echo your results from PHP.
function vote(event) {
event.preventDefault();
$.ajax({
url: "php/core/voting_system.php",
type: "POST",
dataType: 'html',
data: 'bad='+$('input[name="bad"]').val()+'&good='+$('input[name="good"]').val(),
success: function(data){
var votes = $("#votes").val().empty();
$("#votes").html(data+votes);
}
]);
}
I am hitting roadblock after roadblock in my quest to get this JSON usable by PHP, so I'm wondering if someone can help me out here.
I have JSON being stored in the variable divisionsJSON:
var divisionsJSON = JSON.stringify(divisions);
Then I try to use .ajax to post with the following:
$.ajax({
url: "divisions.php",
type: "post",
data: divisionsJSON,
success: function(){
alert("success");
$("#result").html('submitted successfully');
},
error:function(){
alert("failure");
$("#result").html('there is error while submit');
}
});
(I copied this from another question on SO, but have nothing in my html with the id="result" - I think I can delete that part [deletion confirmed])
Then, my divisions.php page contains the following:
<?php
$url = "divisions.php";
$json = file_get_contents($url);
$json = utf8_encode($json);
$elements = json_decode($json);
var_dump($elements);
?>
My inexperience with PHP/ajax combined with my frustration with getting this to work has made me try a bunch of different things. So far I've either gotten NULL or nothing when I load divisions.php. My gut tells me that it's a problem with the ajax, but I'm so inexperienced with PHP that I can't say with confidence that my PHP is correct enough to where I should be getting something back. I've tried var_dump, print_r, echo, absolutely nothing is showing up on divisions.php related to the actual PHP/JSON. Any and all help would be greatly appreciated!
Response with updated code:
I am getting NULL with the following php without the utf8 line, and string(0) "" when I added in the utf8 line:
<?php
$json = json_decode(file_get_contents('php://input'));
$elements = utf8_encode($json);
var_dump($elements);
?>
Any ideas?
Edited for full php page:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>untitled</title>
<link rel="stylesheet" href="styles/reset.css" />
</head>
<body>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript" src="underscore.js"></script>
<script type="text/javascript" src="application.js"></script>
<script type="text/javascript" src="divisions.js"></script>
<?php
print_r($_POST);
?>
</body>
</html>
I've tried multiple lines for the php, print_r($_POST);, json_decode($_POST);, etc. but I'm changing so many things based on what I'm seeing on other SO's and this page that I'm really in a daze.
EDIT: Would this code, which I intended to make an array, not produce JSON? Because it doesn't seem like I'm working with JSON atm.
var divisions = [];
for (var i = 0; i < arr.length; i++) {
if(arr[i].value != "N/A"){
var obj = { "login": arr[i].login,
"value": "http://www.value.net/index/" + arr[i].value};
divisions.push(obj);}
First of all, when dealing with JSON the best approach is to leave it alone as much as possible. Think if it as fragile goods. Anything you do to it could break it.
With that in mind, don't use stringify() and in fact you don't need to as JQuery will detect it and handle it for you (because they know it's fragile).
Second, the option data: in the $ajax() method needs to be given an object. Generally you would do something like this,
data: {mydata:divisionsJSON}
That way you can access the JSON on the backend via
$json = json_decode($_POST['mydata']);
Or, depending on how you have your divisions array set up, you could post it as the object data: is looking for and access it in PHP via $_POST['divisions_key'] = divisions_value; but that makes for all kinds of issues later and hard links the front end to the back end which is very bad (most of the time, exception is below).
Also, if you are expecting a JSON response you'll need to specify that in the original call using the dataType: 'JSON' option so JQuery can handle it appropriately.
$.ajax({
url: "divisions.php",
type: "post",
data: {mydata:divisions},
success: function(response){
$("#result").html(response.message);
},
error:function(response){
$("#result").html(response.message);
}
});
But, before we get too far, that division variable in JS is troubling. Where is that sourced from? Is it a form by any chance? If so, you can use serialize() such that
var divisions = $('#myform').serialize();
This will create key=>value pairs where the key is the name of the form field and the value is (obviously) the value of the field. You can access the values in PHP just as you would normally.
When considering the earlier question about how your array is structured, this is an acceptable case of posting data as the object. If it's a form then the form structure is going to be linked to the backend out of necessity anyway and so the direct use of the object in the data: option is just fine. It's that whole first concept of "leave it alone". The last case here leaves that object alone completely; from the time it leaves the DOM to the time it's received by the handler it's an object 100% of the time.
As #slamborne mentioned in the comment, the correct call is json_decode(file_get_contents('php://input')).
What your call is doing is actually making another call to divisions.php, which is why you're getting NULL back (it doesn't have any data to return to you, as divisions.php doesn't output anything).
On my page I have a search result that contains a list with users where each is followed by an "addfriend" button. Each row contains a username and userID. Meanwhile the ID of the user that requested the searchresult is stored in a Session variable.
When the addfriend-botton is clicked the following 2 things should happen:
Store the userID and $_SESSION['userID'] is a MySQL table which describes the relationship.
Do NOT refresh the page (this the core of my problem) but stay focussed and change the state of the button to e.g. "friend request send". I'm thinking of GetElementByID().style method.
I was thinking of this:
<a href="#" onClick="addFriend('<? echo $_SESSION['userID'];?>','<? echo $rij['userID']; ?>')">
which calls the javascript function addfriend
I was hoping to catch the two ID's like this:
<script>
function addfriend(id1, id2)
{
//server side php code where I use value of
//the client-side javascript variables: +id1+ and +id2+ .
}
</script>
Is this at all possible or I'm I thinking the wrong way? Any suggetions on how to accomplish this?
You are in the right way, inside your addFriend() function, you can call one php file (via AJAX) and send the IDS without refresh the page. I think better you work with Jquery in this case, something like this:
<script>
function addfriend(id1, id2)
{
$.ajax({
type: 'POST',
url: 'yourPHPfile.php',
data: { your_id_1:id1, your_id_2:id2 },
success: function(data){
if(data){
alert('Done!');
}
},
dataType: 'text'
});
}
</script>
And in your PHP File you can do this:
<?php
//receive Ids
$id1 = $_POST['your_id_1'];
$id2 = $_POST['your_id_2'];
//do something here
echo "OK!";
<?
to do this work you need download and add the jQuery plugin in your page, rather into head tag
<head>
<script type="text/javascript" src="jquery.js"></script>
</head>
Good work and don't give up! (:
You can do this using AJAX (asynchronous JavaScript and XML), which is really just a fancy term for "sending stuff to a server with JavaScript and getting a response back, without reloading the page". There's nothing special about AJAX; it just involves using plain old JavaScript to send an HTTP request.
Check out jQuery, a JavaScript library that handles most of the technical stuff for you. Specifically, look at its post() function, which allows you to send data to a PHP script using the $_POST system variable. There are lots of clear examples on that page.
Note that you don't need jQuery to use AJAX; jQuery is just a library that makes things easier. If you really want to learn how the JavaScript side of AJAX works, try following one of the many tutorials out there, such as Mozilla's or this one.
AJAX is the answer you're looking for.
It sounds like you already have a basic understanding of this, but to clarify, Javascript executes on the client side, and PHP executes on the server side. So you would have to make a call back to your server in order to interact with PHP/MySQL.
The purpose of AJAX is to do this without requiring a page refresh.
I have a working PHP registration form that goes through $_POST[] requests to check user inputs.
Username length (3-20)
Username availability
Username /^[A-Za-z0-9_]+$/
etc.
Rather than have it take you to a whole new page to display errors, I want a live request to call for the errors from register.php so they will appear in a div on the registration.
<div id="errors">" . $usernameErrors . "</div>
I've been trying to read up on AJAX but have noticed most codes involve utilizing $_GET[].
What will I have to do to get my current forms integrated with AJAX?
My Current Basic Registration Form Logic:
<form method="post" action="register.php">
<input type="text" name="username" id="username" required />
$usernameErrors
</form>
And register.php contains all of the checks already.
If you're using jQuery, it's pretty simple.
<script type='text/javascript'>
$.post('/register.php',
{username: $('#username').val()
// insert values of other fields here
},
function(response) {
// update your div with errors
$('#errors').html(response);
})
</script>
You should invoke this code, for example, when user changes username in registration form. It will happen in background and update page asynchronously.
Your register.php script should, in this case, emit only errors, not the whole page, or you will see unexpected results. :-)
In order to simplify ajax, you can use jQuery (a very powerful JS lib).
Add jquery***.js to your project and refer it on your page:
<< script type="text/javascript" src="#js/jquery-ui-1.8.16.custom.min.js" />
Then, you create the javascript function that will make the ajax call.
On the ajax call, you specify the php file to call and the function to handle the return of php(callback). On this callback function, you add the error message to body.
function verifyForm(){
$.ajax({
type: "POST",
url: "register.php",
data: "username=NAME_GOT_FROM_FORM_&location=Boston"
}).done(function( returned ) { //the callback
$('#errors').html(returned); // add the string returned to div id=errors
});
}
So, the crux of the problem as you're asking it seems to be that you're (correctly) using a POST request on your register form, but your tutorials all want to use GET. Here's a discussion about the difference between the two methods:
http://thinkvitamin.com/code/the-definitive-guide-to-get-vs-post/
If you're actually registering the user with AJAX (rather than just validating) you should be submitting the AJAX request as a POST. If you're using jQuery, the answer has already been given. If you're not using jQuery, then look for the XMLHttpRequest object in your tutorial, and where its "open" method is called (reference here: http://www.w3.org/TR/XMLHttpRequest/). The first parameter of that function is a request method--change it to "post" rather than "get", and the request will be treated like a POST, which register.php expects.
That being said, it sounds like you just want AJAX to validate the form. In that case, GET is the correct verb to use--all you want to do with AJAX is check data against the database, not actually make a change to data. I would suggest that you actually write a new PHP script like validate_registration.php that will perform only the validation logic in register.php, and then return a JSON array of errors (which would be empty if no errors occurred). You can activate/deactivate your form submit button based on that return value, and let the user submit the form just like your old workflow if everything is okay.
The tl;dr here is that you should read up on what makes $_GET and $_POST different, and then write an AJAX-specific validation script so that you're separating the data-retrieval part of your process from the data-insertion part. Once you understand the difference, the rest should follow.