Memcache not getting deleted through Ajax Call to Controller - php

I have a MVC structure in one project where there is a dropdown on change of which I am calling a Controller as follows..
Javascript Code
function getData(newSelection)//This will get called on change of dropdown
$.ajax({
type: 'POST',
url: '/controller_name/perform',
data: {
'dropDownSelection': newSelection
},
success: function(data){
//alert(data); /* always "failed" */
window.location.href=window.location;
}
});
Now, in perform action (i.e. method named as PerformAction) the call is coming properly.
Perform Action
/* somehow I am forming $key; trust me, its formed correct */
$cache = Zend_Registry::get("cache");
if($cache->delete($key))
echo ("success");
else
echo ("failed");//this is what always returned
exit;
But at some code which executes after above code, I am checking whether cache exits or not, then it is showing as exists.
Code where i am checking
$cache = Zend_Registry::get("cache");
//After building $key.
//$cache->delete($key); //Here it works
$cacheResult = $cache->get($key);
if (!empty($cacheResult)) ) {
//exit("here it is coming, which I dont want for certain situation");
return $cacheResult;
}
$reslut = /* Now I am building new result as per new selection from dropdown */
$cache->set($key,$result,MEMCACHE_COMPRESSED,300);
return $result; //i want this to be returned instead of cached result
So this is the scene.
I want to get fresh result that is built using new selection from dropdown, if I remove comment from $cache->delete($key); above it will always remove cache, but I dont want this.
I want to know where I am going wrong OR is that beacause of AJAX ?

Related

How to run a helper function multiple times for checking live results from the DB

I have a forum project with Laravel 9, and I have made this helper function.
if(!function_exists('new_question')){
function new_question($c) {
$quelist = \DB::table('questions')->get();
$quecount = $quelist->count();
if($quecount > $c){
return 'A new question is added.. please refresh the page..';
}
}
}
So it gets the number of current questions like this:
{{ new_question($queCnt); }}
And then, it will check if the $quecount equals $queCnt or not. And if not, then print the statement A new question is added.. please refresh the page... Therefore the user will understand if any new question is added. But I need to run this helper function after some periods of time (for example, 10 seconds). However, I don't know how to call a function after a custom amount of time.
to run any function after a specific time, you have set the interval for example
// Call the new_question function every 10 seconds
setInterval(new_question, 10000);
// Use an AJAX request to call the new_question function on the
// server
function new_question(){
$.ajax({
url: '{{ url('/new_question') }}?c=10',
success: function(response) {
// Handle the response from the server
console.log(response);
}
});
}
</script>
// to receive get value update helper function
if(!function_exists('new_question')){
function new_question() {
// Get the value of the c parameter from the query string
$c = isset($_GET['c']) ? $_GET['c'] : 0;
// Your code here...
}
}
First, you have to figure out if the number of "content" has changed. Using Laravel, create a function that is accessible through a route, this function would return the number of posts, then, using javascript, you will call that function in an interval (example is 5 seconds) and if the number has changed since the last call, then there's new posts, so you should do some DOM manipulation to update your page to alert the user.
Your server side function would be simple, something like this:
function count_questions() {
$quelist = DB::table('questions')->get();
$quecount = $quelist->count();
$response = array('quecount' => $quecount);
echo json_encode($response);
}
Then, identify how to reach this function through your routing table, and use the below jquery functions:
var quecount = 0;
$(document).ready(function() {
setInterval(function() {
$.ajax({
// change this URL to your path to the laravel function
url: 'questions/count',
type: 'GET',
dataType: 'json',
success: function(response) {
// if queuecount is 0, then set its initial value to quecount
if(quecount == 0){
quecount = response.quecount;
}
if(response.quecount > quecount){
quecount = response.quecount;
new_question_found();
}
}
});
}, 5000);
});
function new_question_found(){
$("#new_questions").html("New questions found");
}
The solution that is coming to my mind is may be too advance or too complex.
This solution need
Laravel scheduler and queue (Jobs)
and web push notification (ex : one-signal)
To reduce the traffic in the back-end you can have job to run like every 10 seconds in the back-end (Laravel scheduler and Queue).
If the question count get increased. you can call a api in the push notification and you can say there is a new question added.
the above work-flow is not explained well but this is in very simple term.
For example:
on frontend side:
const check_new_questions = function() {
const message =
fetch('http://yourserver.com/new_questions_endpoint');
if (message) {
// show message
}
};
// call each 10 seconds.
setInterval(check_new_questions, 10000);
then on backend side:
create a route new_questions_endpoint which will call your function and return result as response.
But note, that receiving all the questions from the table each time could be expensive. Eloquent enables to make a count query without retrieving all the rows.
You can't have this behaviour happen without any form of javascript.
The main way you could do this is by setting an interval via front-end like others have said. If you have any familiarity with APIs and general HTTP protocol, I would recommend you make an API route that calls your helper function; I also recommend responding with an empty body, and using the http status code to determine whether a refresh is needed: 200 for success and no refresh, 205 for success and refresh needed.
So you simply set a fetch api call on timeout, don't even need to decode the body and just use the response status to determine whether you need to run location.reload().
To achieve your requirement as per the comment you need to create an ajax request to BE from FE to check the latest question and based on that response you need to do it.
setInterval(function()
{
$.ajax({
url: "{{url('/')}}/check/questions",
type: "POST",
dataType: "json",
data: {"action": "loadlatest", "id": id},
success: function(data){
console.log(data);
},
error: function(error){
console.log("Error:");
console.log(error);
}
});
}, 10000);//time in milliseconds
the above js code will create an ajax request to Backend, below code will get the latest question 'id'.
$latest_id = DB::table('Questions')->select('id')->order_by('created_at', 'desc')->first();
so either check it in BE and return a corresponding response to FE or return the latest id to FE and check it there.
then show the prompt to refresh or show a toast and refresh after 5 sec
Why do you use function_exists() ? I don't think it's useful in this case.
The easiest way to do what you want is to use ajax and setInterval
Front side:
const check_new_questions = function() {
const data =
fetch('http://yourserver.com/new_questions_endpoint?c=current');
if (data) {
alert(your_message);
}
};
// call each 10 seconds.
setInterval(check_new_questions, 10000);
Back side:
function new_question() {
// Get the value of the c parameter from the query string
$c = isset($_GET['c']) ? $_GET['c'] : 0;
$quelist = \DB::table('questions')->get();
$quecount = $quelist->count();
return ($quecount > $c);
}
I suggest to use c as the last id and to not count questions but just to get the last question id. If they are different, one question or more was inserted.
Attention if you use this solution ( Ajax pulling ) you'll get two requests per 10 seconds per connected users. One for the ajax call and one for for the database call. If you have 10 users a day, it's ok but not if you have 10 thousands. A better but more complex approach is to use Mercure protocol or similar ( https://mercure.rocks/ ).

How to delete multiple records together using IN(of MySQL) in CakePHP 2.6

Basically, I want to do that user will check the checkbox and click on deleteAll button for delete multiple records at once. For this, i fire ajax and get all selected id's and then selected id's send to controller's method.
I am using delete method for remove multiple records from database but it is not working.
And I do not want to delete multiple records using loop.
Is there any other way of CakePHP of delete multiple records at once?
I tried below code:
script.js :
$('#del_all').click(function(){
var selected=[];
$('.check:checked').each(function(){
selected.push($(this).attr('id'));
});
$.ajax({
type: "post",
url: "Users/deleteall", // URL to request
data: {"id":selected}, // Form variables
success: function(response){
alert(response);
}
});
});
Controller method :
public function deleteall(){
$data=$this->request->data['id'];
$user_ids=implode("','",$data);
$user_ids="'".$user_ids."'";
$this->User->delete($user_ids,$cascade=false);
}
try this with deleteall try to use this
public function deleteall()
{
$user=array(1,2,3); // replace with real values
$condition = array('User.id in' => $user);
$this->User->deleteAll($condition,false);
}
Use deleteAll() method
$this->User->deleteAll(array('id' => $user_ids), false);
Note that:
deleteAll() will return true even if no records are deleted, as the conditions for the delete query were successful and no matching records remain.
More information you can find in manual.

Adding Item to Database in Laravel with AJAX and then showing Item

After hours of Googling, I can't seem to find an answer to this seemingly simple problem. I can't add data to a database and show that data without refreshing the page. My goal is to be able to create an object from a form to upload to a database, and then show all the items in database (without the page refreshing). I have tried to get AJAX working many times, but I can't seem to do that. The application works by adding stars to students, so basically I would want to be able to update a students star count without reloading the page. But right now I can't even console.log the submitted form data. My Controller code is like so:
public function addStar(){
$id = Input::get('id');
$user_id = Input::get('user_id');
if(Auth::user()->id == $user_id){
Student::addStar($id);
}
return Redirect::back();
}
And my form:
{{Form::open(array('action'=>'HomeController#addStar','id'=>'addStar','method'=>'post'))}}
{{ Form::hidden('id', $student->id, array('id'=>'id_value')) }}
{{ Form::hidden('user_id', $student->user_id, array('id'=>'user_id_value'))}}
{{ Form::submit('+')}}
{{ Form::close() }}
And my extremely poor attempts at AJAX:
$('#addStar').on('submit',function(e) {
e.preventDefault();
$.ajax({
type: 'POST',
cache: false,
dataType: 'JSON',
url: '/addstar',
data: $('#addStar').serialize(),
success: function(data) {
console.log(data);
},
});
return false;
});
The code works fine if I settle for allowing page reloads, but I don't want that. So essentially, my question is, how do I add data to a database and show it without the page reloading? Thanks so much!
Your controller is doing a redirect after the logic, ajax won't be able to do anything with the response. A one take would be, after adding a start returning the new star rating.
public function addStar(){
$id = Input::get('id');
$user_id = Input::get('user_id');
if(Auth::user()->id == $user_id){
Student::addStar($id);
}
$star_count = //get new star count;
return Response::json(['star_count' => $star_count]);
}
Since controller now returns a json response, the success callback on $.ajax can grab it and do something (update the star count).
#codeforfood,
If you want to grab the response and show it immediately in the page without a reload then you may go with returning a JSON reponse and then handle that response at the client side Javascript for Success or Failure conditions.
Can try something like this if you want:
In the controller addStar() method response:
$data = ['star_count' => 'COUNT OF STARS'];
return json_encode($data);
In the View for that specific Star Div:
<script>
$('#stardiv).on('submit', function (e) {
$.ajax({
type: 'POST',
url: "{{URL::to('xxxxx')}}",
data: $(this).serialize(),
dataType: "JSON",
success: function (data) {
Handle the success condition here, you can access the response data through data['star_count']
},
error: function (data) {
Handle the error condition here, may be show an alert of failure
}
});
return false;
});
</script>
After all this is just one approach, you may try different one which ever suits your need.

Sending ajax request for each element?

I have an app that has rows, each row contains data. The rows are created by the user (just cloning a sample row).
My ajax function looks like this.
save : function(el) {
//Renaming the properties to match the row index and organize
jQuery('#application-builder-layout .builder-row').each(function(row) {
// Iterate over the properties
jQuery(this).find('input, select, textarea').each(function() {
// Save original name attr to element's data
jQuery(this).data('name', jQuery(this).attr('name') );
// Rewrite the name attr
jQuery(this).attr('name', 'application[rows]['+row+'][elements]['+jQuery(this).attr('name')+']');
});
});
//Looping through each row and saving them seperately with new rowkey
setTimeout(function() {
// Iterate over the layers
jQuery('#application-builder-layout .row-box').each(function(row) {
// Reindex layerkey
jQuery(this).find('input[name="rowkey"]').val(row);
// Data to send
$data = jQuery('#application-builder-layout .row-box').eq(row).find('input, textarea, select');
//$data = $data.add( jQuery('#application-builder-layout') );
jQuery.ajax(jQuery('#form').attr('action'), {
type : 'POST',
data : $data.serialize(),
async : false,
success: function( response ) {
//console.log( response );
}
});
});
}, 500);
},
This is the jQuery, it's application style format so this function is inside a var and is called inside a submit function, the problem is not the ajax, looking at it in the console it saves the data fine, just like I have before.
The Problem I cant get all the data into the database (only the last ajax request) take a look below at "Form Data" it shows what my ajax data looks like and how it's inserting into the DB vs how it should insert, I am using json encode and usually this works, but recently I switched to OOP style coding in PHP so I am not sure if that changes anything?
The PHP:
class MyApp {
const Post_Type = 'page';
public function __construct() {
// register actions
add_action('init', array(&$this, 'init'));
}
public function init() {
// Initialize Post Type
add_action('save_post', array(&$this, 'save_post'));
}
//The main save method
public function save_post($post_id) {
// Empty the builder
if($_POST['rowkey'] == 0) {
$builder = array();
}
$builder['rows'][$_POST['rowkey']] = $_POST['application']['rows'][$_POST['rowkey']];
$builder = esc_sql(json_encode($builder));
if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return;
}
if($_POST['post_type'] == self::Post_Type && current_user_can('edit_post', $post_id)) {
// Update the post's meta field
update_post_meta($post_id, 'MY_DATABASE', $builder);
} else {
return;
}
}
}
The above works fine, except its not inserting the data as an array just inserting the last ajax post call, not each. I am sure in my save method I need to reconfig that somehow, but I am just hacking away and cant find info on the web, so I could really use some insight.
I hope I provided enough.
My code summed up: Just to be clear on whats going on here, let me you some basic HTML of my app.
//This gets cloned and the jQuery renames the rowkey to match the index.
<div class="row-box">
<input type="hidden" name="rowkey" value="0">
<div class="builder-row">
<textarea style="display: block;" name="html"></textarea>
<textarea style="display: block;" name="breakingbad"></textarea>
</div>
</div>
So summed up lets say there is 4 rows, the jQuery renames each row, then loops through each and submits an ajax call for each of them. Then the PHP handles the $_POST, in prior applications working with my custom DB I got it to work but working with wp database I am having issues, maybe I am missing something in my method?
Form Data: the ajax form data looks like this (this is the form data inside headers which can be found in the console(firbug) or network(chrome))
//First element
rowkey:0
application[rows][0][elements][html]:A
application[rows][0][elements][breakingbad]:123
Then if there is another row ajax posts again
//Second element
rowkey:1
application[rows][1][elements][html]:B
application[rows][1][elements][breakingbad]:456
So an and so forth, the database looks like this
{"rows":{"2":{"elements":{"html":"B","breakingbad":"456"}}}}
It should be more like this
{"rows":[{"elements":{"html":"A","breakingbad":"123"},{"elements":{"html":"B","breakingbad":"456"}]}
Holy Smokes Batman: I think I got it, It all resides inside how I handle the $_POST ill update soon with an answer..
The database looks good like this
{"rows":[
{"elements":{"html":"A","breakingbad":"123"}},
{"elements":{"html":"B","breakingbad":"456"}}]
}
Now I can continue to build.. whew this was a MASSIVE headache.

Using one delete function for a post jquery request of php request

I'm looking to find out how I can accomplish this next task. I have a controller that loads a view with a table that lists pages in my database. In every row that is made in the table there is a spot for a icon that when clicked will do one of two things.
If the user does not have javascript enabled:
Clicking on the icon will redirect to the delete function in the controller with id of the page as a paramter
Delete controller function will run delete function in model sending page id to delete model function
Delete function in model will delete the page from the database and when returned back to page controller delete function it will redirect back to index function to show list of pages table again.
After redirect it will display a title and message as to a success/fail.
If the user does have javascript enabled:
Send a post to the delete function in controller with jquery post
method with the data page id
Delete controller function will run delete function in model sending page id to delete model function
Delete function in model will delete the page from the database and when returned back to page controller delete function it create a message array for the json object to return to the success function of the post request.
A message with my pnotify plugin will create a message that is formed from that json object and display it to the user
What I would like to know is with doing this how to properly accommodate for these two scenarios? I have started attempting this but would like to some clarification if I have made a mistake so far.
<?php
// Controller delete function
public function delete($content_page_id)
{
if (isset($content_page_id) && is_numeric($content_page_id))
{
$content_page_data = $this->content_page->get($content_page_id);
if (!empty($content_page_data))
{
//update is ran instead of delete to accompodate
//for the soft delete functionality
$this->content_page->update('status_id', 3);
if ($this->input->is_ajax_request())
{
//return json data array
}
}
}
}
?>
Global JS file to be used for multiple tables with delete buttons
/* Delete Item */
$('.delete').click(function(event) {
event.preventDefault();
var item_id = $(this).attr('rel');
$.post(<?php echo current_url(); ?>'delete', { item_id : item_id }, function(data)
{
if (data.success)
{
var anSelected = fnGetSelected( oTable );
oTable.fnDeleteRow( anSelected[0] );
}
}, 'json');
});
I think that you should have two functions in PHP:
public function delete($content_page_id) {
// Your delete code
return "a string without format";
}
public function deleteAjax($content_page_id) {
return json_encode($this->delete($content_page_id));
}
So, when the user has JS enabled, you call deleteAjax passing a parameter in your $.post function to let PHP know that JS is enabled:
$.post(<?php echo current_url(); ?>'delete', { item_id : item_id, js: 1 }, function(data)
{
if (data.success)
{
var anSelected = fnGetSelected( oTable );
oTable.fnDeleteRow( anSelected[0] );
}
}, 'json');
And if JS is disabled, call the other function. You should use an AJAX specialized controller instead a function in the same class.
1) As far as "displaying a message" - the view-itself could be ready for a 'message' if one exists. Bringing us back to...
2) Can you have your delete function return the message you want displayed? Your AJAX approach will ignore this message while your View will display it...
3) I agree that your 'Controller delete function' should 'finish' with different outcomes based on whether the request is AJAX or not. I like what #Skaparate (answered Aug 30 at 18:37) was doing with adding: js:1 In your delete function, you could use this in a simple conditional:
if js = 1
header('HTTP/1.1 200');
else
call view and include/pass-in the 'message'

Categories