I've got 6 different routes that can be chosen from an input select. Each selected route then posts to its own database.
The problem is I get a 500 error back for all of them, but on half of them, it actually posts to the database. I've gone through line-by-line, and other than the variable names, the code is identical. Here's an example of one that doesn't work at all.
submit.js
$('#submit-event').on('click', function() {
event.preventDefault()
let title = $('#title').val()
let type = $('#type').val() // for selecting which DB
let start = $('#start').data('DateTimePicker').date()
let end = $('#end').data('DateTimePicker').date()
let data = {
'_token': token,
'title': title,
'start': start,
'end': end
}
console.log(type); // logs the correct POST route
$.ajax({
method: 'POST',
url: type,
data: data,
success: function(data) {
console.log(data);
},
error: function(err) {
console.log(err)
}
});
})
routes.php
Route::post('/createmeeting', [
'uses' => 'MeetingController#postCreateMeeting',
'as' => 'createmeeting'
]);
MeetingController.php
class MeetingController extends Controller
{
// Get Meeting from DB - works
public function getMeetings()
{
$meetings = Meeting::orderBy('created_at', 'desc')->get();
return $meetings;
}
// Add new Meeting to DB - doesn't work (500 error)
public function postCreateMeeting(Request $request)
{
if (!request['_token']) {
return redirect()->route('calendar')->with(['message' => "You must be logged in"]);
}
// Save Meeting
$meeting = new Meeting();
$meeting->title = $request['title'];
$meeting->start = $request['start'];
$meeting->end = $request['end'];
if ($request->user()->meetings()->save($meeting)) {
$message = 'Event successfully added to calendar';
return redirect()->route('calendar')->with(['message' => $message]);
}
return redirect()->route('calendar')->with(['message' => $message]);
}
}
Responses to similar problems suggest a problem with the token, but I test for that here. Any idea where the mistake could be happening?
Related
I have some problems with my ajax call, I have a collection group and when I click on show link it should show me the collection's tasks.The problem is when I try to create new tasks for the current collection.I made 50% of the problem, because it creates the records in database, but something strange happen.
Form is already submitted even If I do not click the create button
After ajax call, it creates the records in database, but it does not append the newly created element, it shows me this:
Ajax call response
Here is my ajax script:
$(document).ready(function() {
// store task
$('#create-task').click(function (event) {
event.preventDefault();
$.ajax({
type: 'post',
dataType: 'json',
data: $('#create-task-form').serialize(),
success: function (data) {
$('#create-task-form').trigger('reset');
$('#createTaskModal').modal('hide');
$('.collections').append('<li>' + data.name + '</li>');
}
});
});
});
I did not set the url, because when I do that it shows me something like this, and I do not know why.
Duplicate collection/collection/id
Set the url
Routes:
// Collection routes
Route::prefix('collections')->middleware('auth')->group(function() {
Route::get('/', 'CollectionController#index')->name('collections.index');
Route::post('/', 'CollectionController#store')->name('collections.store');
Route::get('/{collection}', 'CollectionController#show')->name('collections.show');
Route::get('/{collection?}/edit', 'CollectionController#edit')->name('collections.edit');
Route::patch('/{collection?}', 'CollectionController#update')->name('collections.update');
Route::delete('/{collection?}', 'CollectionController#destroy')->name('collections.destroy');
Route::post('/{collection?}', 'CollectionController#storeTask')->name('tasks.store');
});
Controller
public function storeTask(Request $request)
{
$attributes = $request->validate([
'name' => 'required|min:3',
'description' => 'nullable|min:3',
'status' => 'required',
'due' => 'nullable|date'
]);
$attributes['collection_id'] = $request->collection;
$task = Task::create($attributes);
return Response::json($task);
}
PS: I can still create records, even the validation from back-end fails!
Based on your image your routing is wrong.
You get a 404 for trying to access collections/collections twice leading to a non existing URL of course.
A solution to this would be:
url: {{ url('/collections/25') }},
Using a simple Ajax GET request to retrieve some data, it successfully checks if($request->ajax()) {} but then fails any validation because there is no data in the Request $request variable. This happens only on the production server, on localhost everything works fine.
The console shows the intended URL https://example.com/employeeInfo?id=1, then error 422 (Unprocessable Entity). Output from error: function(jqxhr, status, exception) { alert('Exception:', exception); } gives an empty alert message.
View
<script>
(function ($) {
$(document).ready(function() {
$(".team-pic").off("click").on("click", function() {
$id = $(this).data('id');
// Get data
$.ajax({
type: 'GET',
url: 'employeeInfo',
data: {'id':$id},
success: function(data){
var obj=$.parseJSON(data);
// Show output...
},
error: function(jqxhr, status, exception) {
alert('Exception:', exception);
}
});
});
});
}(jQuery));
</script>
Route
Route::get('/employeeInfo', 'EmployeeController#get');
Controller
public function get(Request $request) {
if($request->ajax()) {
$this->validate($request, [
'id' => 'required|integer',
]);
// Id
$employee = Employee::find(request('id'));
// Create output
$data = ...
echo json_encode($data);
}
}
If I were you, I would use a RESTful API with route model binding, specifically the explicit binding.
RouteServiceProvider.php
public function boot()
{
parent::boot();
Route::model('employee', App\Employee::class);
}
Route
Route::get('api/employees/{employee}', 'EmployeeController#get');
Controller
public function get(Employee $employee)
{
// The id being valid is already done by forcing it to be an Employee
// It is also an ajax call because it is going to the api route
// This will json_encode the employee object.
return $employee;
}
im not sure how to do this in laravel. Im trying to do a simple ajax request to my controller. Then in my controller return the values that i sent through so i can console.log the data.
However im having a problem doing so.
Ajax Request:
$.ajaxSetup({
headers: { 'X-CSRF-Token' : $('meta[name=_token]').attr('content') }
});
jQuery.ajax({
url:'/group/create',
type: 'GET',
data: {
name: groupName,
colour: "red"
},
success: function( data ){
console.log(data);
},
error: function (xhr, b, c) {
console.log("xhr=" + xhr + " b=" + b + " c=" + c);
}
});
Route:
Route::get('/group/create', ['middleware' => 'auth', 'uses' => 'GroupController#create']);
Controller:
public function create()
{
$data = Request::all();
return json_encode($data);
}
Now when i console.log the returned data it shows at the exact html for the page im on. Any ideas?
Check on the browser console-network-lastprocess- preview, it could show you the error.
Also you can "console log" from the controller using Log::info('useful information') and it will show it to you at storage/logs/laravel.log
You should use Laravel's JSON return: return response()->json(['name' => 'Abigail', 'state' => 'CA']);
But also what you're doing is actually calling a GET with data however it should be a POST in this case. If you have to provide data to a controller, it's a POST and you can just return the data that way.
So change your AJAX to be POST and then you can use the Request::all() to get all data, and return it via JSON.
I often use the patchEntity function to hydrate my entity with form data, and it works fine, even with an ajax request.
But when I tried to insert data from an an ajax request with JSON data, patchEntity failed to retrieve the data.
My ajax request is very simple:
var rate = function (user, rate, success, error) {
$.ajax({
type: "POST",
url: baseUrl + 'rate/add',
data: {
id: this.id,
user: user.id
rate: rate
},
dataType: 'json',
success: success,
error: error
});
});
In my Rate controller, my add function looks like:
public function add()
{
if ($this->request->isAjax()) {
$this->layout = 'ajax';
$rate = $this->Rate->newEntity();
if ($this->request->is('post')) {
$rate = $this->Rate->patchEntity($rate, $this->request->data);
if ($rate->errors()) {
$this->set([
'status' => 500,
'message' => $rate->errors()
]);
} else {
if ($this->rate->save($rate)) {
$this->set([
'status' => 200
]);
} else {
$this->set([
'status' => 500,
'message' => $rate->errors()
]);
}
}
return $this->render('/Ajax/result');
}
}
This throw an exception:
Cannot insert row, some of the primary key values are missing. Got (,
, ), expecting (id, user)
I can save my data using this instead of $this->Rate->patchEntity($rate, $this->request->data);
$rate['id'] = $this->request->data['id'];
$rate['user'] = $this->request->data['user'];
$rate['rate'] = $this->request->data['rate'];
What sort of array do I have to pass to patchEntity function to makes this works?
Thanks to ndm's comment, I've checked the Rate Entity and just removed this part which was automatically generated by bake:
protected $_accessible = [
'rate' => true,
];
I'm to trying to store a sort order to each article within a help centre for my new site using Laravel 5 and having a bit of trouble getting it to work. I'm using jQuery UI's .sortable for arranging the elements on the page, and since there are going to be multiple sections throughout the site where areas are sortable, my jQuery script is built in a way for a 'one script for all' purposes. Hence the use of data-* attributes and route name references.
Here is the code I've got so far:
routes.php
Route::post('admin/help-centre/category/{category_id}/section/{section_id}/article/sort-order', 'AdminHelpCentreArticleController#sortOrder');
AdminHelpCentreArticleController.php
public function sortOrder($category_id, $section_id)
{
/* Return ------------------------------------- */
return [
'category_id' => $category_id,
'section_id' => $section_id
];
}
show.blade.php (Admin Article Listing)
<ul id="help-center-articles-sort" class="sortable">
#foreach ($helpCentreArticles as $helpCentreArticle)
<li class="sortable-element" data-sortable-element-id="{{ $helpCentreArticle->id }}">
{{ $helpCentreArticle->title }}
</li>
#endforeach
</ul>
Save Order
scripts.js (includes CSRF Token _token)
var csrfToken = $('meta[name="csrf-token"]').attr('content');
$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
if (options.type.toLowerCase() === 'post')
{
options.data += options.data?'&':''; // add leading ampersand if `data` is non-empty
options.data += '_token=' + csrfToken; // add _token entry
}
});
$(document).ready(function() {
$('.sortable').sortable();
$('.sortable-save').on('click', function(e) {
e.preventDefault();
var route = $(this).attr('href'),
sortableID = $(this).attr('data-sortable-id');
var data = $('#' + sortableID + ' .sortable-element').map(function() {
return $(this).attr('data-sortable-element-id');
}).get();
$.ajax({
type: 'POST',
url: route,
dataType: 'json',
data: { id_array: data },
success: function(data) {
console.log(data);
}, error: function(data) {
console.log(data);
},
});
});
});
Everything so far is working in terms of the return response in the console, which is Object {category_id: "1", section_id: "1"}. But no matter what I try, I cannot seem to pass through the data map to the controller to use it.
I've tried a bunch of guesswork since I cannot find a single decent tutorial on AJAX in Laravel 5 anywhere, and I've tried things such as adding a $data parameter to the sortOrder() method, I've tried Input::all() and Request::all but it all returns errors (I'm guessing cause it's not an actual form?).
Once I've got the data to be passed through to the controller I'll be able to save the sort order to the database easily enough. But I can't quite get to that stage, any ideas?
EDIT
I should probably note that I do have a HelpCentreArticle model and a HelpCentreArticleRequest request too, here's some of the code from each file in case they are also needed:
HelpCentreArticle.php
class HelpCentreArticle extends Model {
protected $fillable = [
'category_id',
'section_id',
'title',
'content',
'excerpt',
'is_visible',
'sort_order',
'created_by',
'updated_by',
];
}
HelpCentreArticleRequest.php
class HelpCentreArticleRequest extends Request {
/* Authorization ------------------------------ */
public function authorize()
{
return true;
}
/* Validation rules --------------------------- */
public function rules()
{
$rules = [
'title' => 'required|min:3',
'content' => 'required|min:10',
];
return $rules;
}
}
I wasn't sure if I needed to add HelpCentreSectionRequest $request as the last parameter of the sortOrder() method, so I could use $request->all() but it just returns a 422 (Unprocessable Entity) in the console log.
So it appears that the correct way was to use Input::get('id_array'); instead of $_POST['id_array'];, which I tried, but when I originally tried this I wasn't including use Input; at the top of my controller, as I thought this was already accessible, but it wasn't.
Adding use Input;, and using Input::get(); is now working as expected.
Here is the updated code:
AdminHelpCentreArticleController.php
public function sortOrder($category_id, $section_id)
{
/* Query Select ------------------------------- */
$helpCentreCategory = HelpCentreCategory::findOrFail($category_id);
$helpCentreSection = HelpCentreSection::findOrFail($section_id);
/* Variables ---------------------------------- */
$id_array = Input::get('id_array');
$sort_order = 1;
/* Query Update ------------------------------- */
foreach($id_array as $id) {
$helpCentreArticle = HelpCentreArticle::where('id', $id)->first();
$helpCentreArticle->sort_order = $sort_order;
$helpCentreArticle->save();
$sort_order++;
}
/* Return ------------------------------------- */
return ['success' => true];
}
Then you can obviously access success for an if else statement in your jQuery to manipulate the page.
My implementation of UI sortable with Laravel
index.blade.php
...
#foreach($photos as $photo)
<tr data-sortable="{{ $photo->pivot->position }}" data-id="{{ $restaurant->id }}" data-photo-id="{{ $photo->pivot->photo_id }}">
<td>
<i class="fa fa-sort" aria-hidden="true"></i>
</td>
...
</tr>
#endforeach
<script type="text/javascript">
$("#sortable-ui tbody").sortable({
helper: fixHelper,
update: function(event, ui) {
$("#sortable-ui tbody tr").each(function(index){
console.log($(this).data('id')+', '+(index+1));
$.ajax({
url: '{{ route('owner.photo.update.position') }}',
type: 'POST',
data: 'restaurant_id='+$(this).data('id')+'&photo_id='+$(this).data('photo-id')+'&position='+(index+1)
})
.done(function (response) {
console.log(response);
})
.fail(function (jqXhr) {
console.log(jqXhr);
});
});
}
}).disableSelection();
</script>
scripts.js
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
AjaxController.php
public function updatePhotoPosition(Request $request)
{
$restaurant = $this->restaurantRepository->getById($request->get('restaurant_id'));
$photoId = $request->get('photo_id');
$photo = $restaurant
->photos()
->wherePivot('photo_id', $photoId)
->first();
$photo->pivot->position = $request->get('position');
$photo->pivot->save();
}