I try to post json with a form using slim.
If I use a rest api, it works. I set this as the body :
{
"url": "http://link.com"
}
Posting to 'api/generate' :
<?php
use Shorty\Models\Link;
use Shorty\Presenters\ErrorPresenter;
use Shorty\Presenters\LinkPresenter;
$app->post('/api/generate', function () use ($app) {
$payload = json_decode($app->request->getBody());
if(/*empty($payload) ||*/ !isset($payload->url) || empty(trim($payload->url))){
$app->response->setStatus(400);
return $app->response->write(
new ErrorPresenter('1000', 'A URL is required.')
);
}
if(!filter_var($payload->url, FILTER_VALIDATE_URL)){
$app->response->status(400);
return $app->response->write(
new ErrorPresenter('1001', 'A valid URL is required.')
);
}
$app->response->setStatus(201);
$link = Link::where('url', $payload->url)->first();
if($link){
return $app->response->write(
new LinkPresenter($link)
);
}
$newLink = Link::create([
'url' => $payload->url
]);
$newLink->update([
'code' => $newLink->generateShortCode($newLink->id)
]);
return $app->response->write(
new LinkPresenter($newLink)
);
});
It returns what is expected :
{"url":"http:\/\/link.com","generated":{"url":"http:\/\/localhost:200\/phpacademy\/shorty\/public\/a","code":"a"}}
But I want to send the json through a form. If use this :
<form id='userForm'>
<input type="text" name="url">
<input type="submit" value="Get link!">
</form>
<!-- where the response will be displayed -->
<div id='response'></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js "></script>
<script>
$(document).ready(function(){
$('#userForm').submit(function(){
// show that something is loading
$('#response').html("<b>Loading response...</b>");
/*
* 'post_receiver.php' - where you will pass the form data
* $(this).serialize() - to easily read form data
* function(data){... - data contains the response from post_receiver.php
*/
$.ajax({
type: 'POST',
url: 'api/generate',
data: $(this).serialize()
})
.done(function(data){
// show the response
$('#response').html(data);
})
.fail(function() {
// just in case posting your form failed
alert( "Posting failed." );
});
// to prevent refreshing the whole page page
return false;
});
});
</script>
</body>
</html>
It is not working.
I get {"error":{"code":"1000","message":"A URL is required."}}.
But I see that "url=http%3A%2F%2Flink.cok" have been posted.
I needed to send json, but json as "name:value", not the default "name: name, value: value". So I found that :
var data = { };
$.each($('form').serializeArray(), function() {
data[this.name] = this.value;
});
data = JSON.stringify(data);
I'm building a data object, with each properties as "name:value". Then parse the object into a string.
Related
The function below is called through a POST request. I need to retrieve URL from my database and open the link in a new tab. I'm using the Redirect::away() function for this. But it gives a MethodNotAllowedHttpException. I have tried calling this function in a GET request and it works perfectly fine.
public function generateURL(Request $request) {
$screenRow = \App\ScreenshotRow::find($request->input('row_ID'));
$baseURL = $screenRow->BaseURL;
$screenshot = \App\Screenshot::where('Setname', '=', $screenRow->Setname)->get();
$pageURL = $screenshot[0]['PageURL'];
if ($baseURL == "") {
return Redirect::away($PageURL);
}
else
return Redirect::away($baseURL);
}
Is there any way to calling this function in response to a POST request?
I would simply use an Ajax Form and redirect the User with Javascript.
Make sure to give your Form an ID
<form id="myForm" method="POST" action="{{ route('your.route') }}">
...
...
<button type="submit">Submit the Form</button>
And make this Form working with Ajax
<script>
$('#myForm [type="submit]').click(function(e){
e.preventDefault();
var form = jQuery(this).parents("form:first");
var dataString = form.serialize();
var formAction = form.attr('action');
$.ajax({
type: "POST",
url : formAction,
data : dataString,
success : function(data){
var url = $.parseJSON(data.responseText);
console.log(data);
// Redirect to a new tab with the given url
window.open(url.success, '_blank');
},
error : function(data){
var error = $.parseJSON(data.responseText);
console.log(error);
// Do what ever you want with an Error Message
alert(error)
}
},"json");
});
</script>
Okay - So if the Form receives a success Message, the success function is executed, otherwise the error function.
Lets go to the Backend Controller which handles the Request
public function generateURL(Request $request) {
$screenRow = \App\ScreenshotRow::find($request->input('row_ID'));
$baseURL = $screenRow->BaseURL;
$screenshot = \App\Screenshot::where('Setname', '=', $screenRow->Setname)->get();
$pageURL = $screenshot[0]['PageURL'];
// Return a JSON Success Message with a Success HTTP Status Code
if ($baseURL == "") {
return response()->json(['success' => $PageURL], 200);
}
// Return a JSON Error Message with a Error HTTP Status Code
else
return response()->json(['error' => $baseURL], 400);
}
Now if your Backend throws a Success Message the success function of the Ajax Form is called which redirects to a new tab based on the given url which you passed in your Backend Controller Success Response.
NOTE
To avoid the tokenmismatchexception on an Ajax Request, you should add the csrf_token to your meta Section in your <head>.
<meta name="csrf-token" content="{{ csrf_token() }}">
And fetch this csrf_token on every Form Request
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
Since I needed a server side language I used PHP. However I cannot write the data coming from the ajax using the JSON.stringify method.
$('#add-order').on('click',function(){
//create an object for orders
var order = {
name : $('#name').val(),
drink : $('#drink').val()
};
$.ajax({
url : 'add_order.php',
type : 'POST',
data : order,
dataType : 'json',
success : function(newOrder){
console.log(newOrder.name);
$('#orders').append('<li>' + newOrder.name + ' : ' + newOrder.drink + '</li>');
},
error: function(){
console.log('error connecting');
}
});
});
Here's the index.php
<h4>Add a Coffee Order</h4>
<ul id="orders">
</ul>
<p><input type="text" id="name"></p>
<p><input type="text" id="drink"></p>
<button type="submit" id="add-order">Add</button>
add_order.php
if (isset($_POST['submit'])) {
$orders = $_POST['data'];
$orderFile = fopen('api/orders.json', 'w');
fwrite($orderFile, $orders);
fclose($orderFile);
}
When I hard coded any string to fwrite($orderFile, "my orders") it will write on the orders.json however when I used the $orders it's not working. Am i missing something here?
you're posting to api/orders.json which is incorrect, you should be posting to the file that processes the request, like index.php.
Passing an object as the data parameter does not convert it to json, you have to actually do it yourself. So if you want $_POST['data'] to hold the order data as json
$.ajax({
url : 'index.php',
type : 'POST',
data : {data: JSON.strinify(order)},
dataType : 'json',
success : function(newOrder){
console.log(newOrder.name);
$('#orders').append('<li>' + newOrder.name + ' : ' + newOrder.drink + '</li>');
},
error: function(){
console.log('error connecting');
}
});
Anyways I found already the solution. First I did was to serialize the inputs instead of using stringify.
var order = {
name : $('#name').val(),
drink : $('#drink').val()
};
var inputs = $('form').serialize();
$.ajax({
url : 'add_order.php',
type : 'POST',
data : inputs,
dataType : 'json',
//some codes here...
});
Then in my php file which is the add_order.php, I fetch the values passed by the data and make them as an array. I also make used of file_get_contents to read on the json file and file_put_content to write on the file as json.
$ordersFile = 'api/orders.json';
$order = array();
//grab the form input
$formData = array(
'name' => $_POST['name'],
'drink' => $_POST['drink']
);
$jsonOrders = file_get_contents($ordersFile);
$order = json_decode($jsonOrders, true);
echo json_encode($formData);
array_push($order, $formData);
file_put_contents($ordersFile, json_encode($order, JSON_PRETTY_PRINT));
But if you still have shorter solution then let me know.
This is my JavaScript in index.php:
MyModel = Backbone.Model.extend({
defaults: {
myID: "",
myName: ""
},
urlRoot: 'testAjaxAdd',
sync: function(method, model, options) {
options = options || {};
options['data'] = {};
options.data["myID"] = model.get("myID");
options.data["myName"] = model.get("myName");
options.data = JSON.stringify(options.data);
return Backbone.sync.apply(this, arguments);
}
});
MyView = Backbone.View.extend({
el: '.page',
render: function(){
var template = _.template($('#add-owner-template').html(), {});
this.$el.html(template);
},
events: {
'submit .create-owner-form': 'saveOwner'
},
saveOwner: function(events) {
var myName= $('input#myName').val();
var owner = new MyModel({
'myID': "111",
'myName': myName
});
owner.save({},{
success: function(model, response, options) {
console.log('success');
console.log(response); // show $_POST from actionSaveOwner in Controller
console.log(model.toJSON()); // show model
console.log(model.get('myID')); // show owner dbcID
console.log(model.get('myName')); // show owner userID
console.log(JSON.stringify(options)); // show options
console.log(options.data["myID"]); // this is shown undefined in console
console.log(options.data["myName"]); // this is shown undefined in console
},
error: function(model, response, options) {
console.log('error');
console.log(response);
console.log(model.toJSON());
}
});
}
});
I have put the code below in very first line within my javascript codes:
Backbone.emulateHTTP = true;
This is my html part of the form, it also a javascript template:
<script type="text/template" id="add-owner-template">
<form class='create-owner-form'>
<label>Name</label>
<input type="text" name="myName" id="myName"/>
<button type="submit" class="btn createcontbutton">Create</button>
</form>
</script>
This is my very simple action in Controller to test out if my backbone works or not:
public function actionTestAjaxAdd()
{
header('Content-type: application/json');
echo CJSON::encode($_POST);
}
However, this is what I see from console in POST tab:
Parameters application/x-www-form-urlencoded Do not sort
{"myID":"111","myName":"i...
But, the $_POST in controller action is nothing when i display it back in console from response.
I finally solved this myself using file_get_contents("php://input") .
I have done to make control autocomplete, but I have a problem to post data with jquery.
<input type="text" id="matakuliah" class="med" name="matakuliah">
<script type="text/javascript">
$(this).ready( function() {
$("#matakuliah").autocomplete({
minLength: 1,
source:
function(req, add){
$.ajax({
url: "<?php echo site_url('bahanAjar/lookup'); ?>",
dataType: 'json',
type: 'POST',
data:req,
success:
function(data){
if(data.response =="true"){
add(data.message);
}
},
});
},
});
});
</script>
on my controller
function lookup(){
// process posted form data (the requested items like province)
$keyword = $this->input->post('term');
$data['response'] = 'false'; //Set default response
$query = $this->matakuliah_model->lookup($keyword); //Search DB
if( ! empty($query) )
{
$data['response'] = 'true'; //Set response
$data['message'] = array(); //Create array
foreach( $query as $row )
{
$data['message'][] = array(
'id_matakuliah'=>$row->id,
'value' => $row->matakuliah,
''
); //Add a row to array
}
}
if('IS_AJAX')
{
echo json_encode($data); //echo json string if ajax request
}
else
{
$this->load->view('admin/bahan_ajar/form_manage_file_view', $data); //Load html view of search results
}
}
The code work it well, but I want to add parameter to call database.
$query = $this->matakuliah_model->lookup($keyword, $id_matakuliah);
like this. how I can get
$this->input-<post('id_matakuliah')
from jquery before.;
and I have another textbox for fill value of autocomplete from textbox matakuliah.
`<input type="hidden" id="matakuliah_post" class="med" name="matakuliah_post">`
When I'm use autocomplete textbox automatic fill another textbox, please help me.
In this case req will contain {term:"your search term"}. Your can extend this javascript object to pass extra data. If you want to post id_matakuliah, you can assign its value like following before $.ajax call:
req.id_matakuliah = "Whatever you want to send";
This is my first attempt to prototype. I want to initiate an AJAX request that should get a JSON response and alert that. I have done following so far.
JS:
<script type="text/javascript">
function ajaxRequest() {
var url = '/ajaxresponse';
new Ajax.Request( url, {
method: 'get',
onSuccess: function(transport,json) {
alert(json ? Object.inspect(json) : "no JSON object");
},
onFailure: function(){
alert('Something went wrong...')
}
});
}
</script>
HTML:
<a href='javascript:ajaxRequest();'>Testing AJAX</a>
JSON source:
function ajaxresponse() {
// Data
$data = array("New York", "New Yorkshire", "New Jersey");
// encode and return json data
echo json_encode( $data );
}
On clicking "Testing AJAX" link I am getting following result in alert box:
no JSON object
Any idea ?
Thanks
I dont see any second variable passed to onSuccess handler in prototype. Look here. There is only transport object. So this should help:
...
onSuccess: function(transport) {
var json = transport.responseText;
alert(json ? Object.inspect(json) : "no JSON object");
},
...