Save to database in yii2 - php

I am trying to save to a database in yii2 using ajax but I am getting errors. I just want to insert the value or rate which is "up" into the database and I don't want to use a form, just on-click of a button.
This is my controller
public function actionThumbs()
{
$thumbs = new Thumbs;
$thumbs->user = Yii::$app->user->identity->email;
$thumbs->topic_id = Yii::$app->getRequest()->getQueryParam('id');
$thumbs->rate = $_POST["rate"];
if ($thumbs->load(Yii::$app->request->post()) ) {
$thumbs->load($_POST);
$thumbs->save();
return $this->redirect(['blog', 'id' => Yii::$app->getRequest()->getQueryParam('id')]);
}
return $this->redirect(['blog','id' => Yii::$app->getRequest()->getQueryParam('id')]);
}
This is my this is my ajax file
$("#mys").click(function() {
var rate = "up";
$.ajax({
type: 'POST',
url: 'vot/frontend/web/index.php?r=site%2Fthumbs',
data: 'rate='+rate,
success: function (rate) {
alert("test");
},
error: function (exception) {
alert(exception);
}
});
});
the view
<div>
<?= Html::Button('ups', ['class' => 'btn btn-primary', 'name' => 'mys' ,'id'=>'mys']) ?>
</div>
I get this alert error
The page at localhost says":
"[object Object]"

By default Yii2 controller doesn't accept POST request without _csrf protection, so there are 2 ways here:
1 - disable csrf:
public function actionThumbs() {
$this->enableCsrfValidation = false;
//your code here
}
2 - Send post request via ajax with _csrf token:
In your layout/main.php file, put this: <?= Html::csrfMetaTags() ?>
Before your "ajax" code, call this:
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="_token"]').attr('content')
}
});
//Your ajax code here

Related

Laravel 5.4 - MethodNotAllowedHttpException in RouteCollection.php line 233

In my laravel 5.4 app, i have a crud module. for the edit bit, the data is rendered in a bootstrap modal. the data is pulled successfully but on hitting the update button, the error shown is returned.
here's my blade form that's rendered in the modal:
<form id="formEdit" class="form-horizontal" role="form" method="put">
//form elements
</form>
here's the ajax that handles it:
//edit_id is defined globally
$('#updateClass').click(function(){
var name = $("#formEdit #name").val();
var status = ($('#formEdit #status').prop("checked") == true) ? 1 : 0;
var token = $('meta[name="csrf-token"]').attr('content');
var id = edit_id;
var url = "classes/update/"+id;
var formdata = {
'name' : name,
'status' : status,
'_token' : token
};
$.ajax({
method: "PUT",
url: url,
data: formdata,
dataType: "json"
})
.done(function(data) {
//
})
.fail(function(data) {
//
});
});
});
updateClass is the button that displays the edit form on the modal..
here's my routes in web.php:
Route::resource('classes', 'ClassesController');
Route::group(['prefix' => 'admin'], function () {
Route::get('classes', 'ClassesController#index');
Route::get('classes/edit/{id}', 'ClassesController#edit');
Route::put('classes/update/{id}', 'ClassesController#update');
});
and finally, my update function in the classes controller:
public function update(Request $request, $id)
{
$validator = $this->validator($request->all());
$errors = $validator->errors();
$errors = json_decode($errors);
if ($validator->passes())
{
Dl_class::find($id)->update($request->all());
return response()->json();
}
else
{
return response()->json($errors, 422);
}
}
what i'm i missing?
To send PUT request from form you need to send a hiddne input element named as method. Something like this:
<input type='hidden' name='_method' value='PUT'>
there is a helper method to do the same like:
{{ method_field('PUT') }}
Only then Laravel can recognize your PUT request.
Or alternatively, you can enclose this value to your ajax call also Something like:
var formdata = {
'name' : name,
'status' : status,
'_token' : token,
'_method' : 'PUT'
};

PHP Laravel : TokenMismatchException in VerifyCsrfToken.php line 67

Here the scenario is, I want to fetch some data from database and show it to user. While someone give some input and save it to database and I put a status with that which is always "0" until someone see it. So whenever a input has submitted user will see a pop up screen with that new data has inserted in another page. Here the problem is when ajax got some value with status "0" it shown it to screen but when it couldn't fetch any value ( when all the status value is 1)it shows error in console :
TokenMismatchException in VerifyCsrfToken.php line 67
.
How do I solve the issue , any possible suggestion please ?
Here is the route:
Route::post('/unread',[
'uses'=>'ItemController#getUnread',
'as'=>'unread'
]);
Route::post('/s_update',[
'uses'=>'ItemController#status_update',
'as'=>'s_update'
]);
Here is the controller :
public function getUnread()
{
$items=DB::select(DB::raw("SELECT count(*) as total from items where status =0"));
// $data=mysql_fetch_assoc($items);
return Response::json($items);
}
public function status_update()
{
$items=DB::select(DB::raw("UPDATE items SET status=1 WHERE status=0"));
return Response::json($items);
}
and here is the ajax call :
<script type="text/javascript">
setInterval(function(){
$(".container").load("list", function(){
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
type : "POST",
url : "{{url('unread')}}",
dataType : 'json',
success : function(data) {
$.each(data,function(index,subcatObj){
if(subcatObj.total != '0')
{
var yes = confirm('You have '+subcatObj.total+' new messages');
if(yes){
status_update();
}
}
});
},
});
});
}, 3000);
function status_update(){
$.ajax({
url:"{{url('s_update')}}",
method:"POST",
});
}
</script>
Change this route
Route::post('/unread',[
'uses'=>'ItemController#getUnread',
'as'=>'unread'
]);
to
Route::get('/unread',[
'uses'=>'ItemController#getUnread',
'as'=>'unread'
]);
I think this is because you are not sending the laravel csrf token in the post.
You need to send a field called "_token" in the json which is the csrf_token provided.
See here : https://laravel.com/docs/5.3/csrf
{{ csrf_field() }}
use this to generae csrf token in your form

Laravel 5: Redirecting to external link on POST request

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')
}
});

Laravel 5 AJAX Sort Order data (jQuery Sortable) with no HTML form

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();
}

how could i retrieve profile data in a modal using ajax in php?

here's the deal, i've created a search results page and i'd like to open a modal and retrieve profile data via ajax in php but i'm not too sure on how i can implement it. I've created the modal but but i don't know how i would go about getting the 'id' from clicking the search result, passing it onto ajax to retrieve the profile details.
Twitter has this kinda feature; when you click a username in a feed and it opens a modal and gives you a brief overview of the profile with a link to the full profile.
It would mean so much to me if someone could help me out or point me in the right direction! :)
P.S. I'm using codeigniter, if anyone is wondering what framework i'm using.
EDIT: here's the code
<?php
/*** PHP Search Results Loop ***/
if ($num > 0){
foreach ($query->result_array() as $row)
{
echo "link to ajax"'>";
}
} else {
echo "<strong>results not found :(</strong>";
}?>
<script> /* jQuery Runs When Result Has Been Clicked */
$('#ResultText').click(function() {
var targetid = {
id: /*Profile Id*/,
ajax: '1'
};
/* Modal Code */
$('.modal-backdrop, .modal-profilebox').css('display', 'block');
$('.modal-backdrop').animate({'opacity':'.50'}, 100, 'linear');
$('.modal-profilebox').animate({'opacity':'1.00'}, 200, 'linear');
$.ajax({
url: "<?php echo site_url('finder/modal'); ?>",
type: 'POST',
data: form_data,
success: function(profileData) {
$('.modal-profilebox').html(profileData);
}
});
return false;
});
</script>
Try something like this
public function ajax_user_profile($user_id)
{
if( !$this->input->is_ajax_request() )
{
redirect('/'); //only allow ajax requests
}
try
{
$user_profile = ''; //grab user object from DB
if( !$user_profile )
throw new Exception("Error Message");
}
catch(Exception $e)
{
log_message('error', $e->getMessage());
echo json_encode(array(
'error' => 1
));
exit;
}
$data = $this->load->view(array(
'some_view' => 'some_view',
'user' => $user_profile
), TRUE); //NO Template, just the view by adding TRUE
echo json_encode(array(
'error' => 0,
'data' => $data
)); //return view data
}
--
<a rel="modal" data-user-id="1" >Joe Bloggs</a>
--
(function($){
var userObj = {
init : function(){
this.getProfile();
},
getProfile : function(){
var modalSearch = $("a[rel='modal']");
modalSearch.on('click', function(){
//trigger the modal window
//request ajax
$.ajax({
url : BASEPATH + 'users/profile/' + $(this).data('user-id'),
type : 'POST',
dataType: 'json',
success : function(callback){
if(callback.error ==0)
{
$('.modal-profilebox').html(callback.data);
}
}
});
});
}
}
$(function(){
userObj.init()
});
})(jQuery);

Categories