Dynamic data load by ajax in laravel - ajax

I have Post show method where i show each post by their id and this is how it's look like:
$post = Post::find($id);
$comments = Comment::where('post_id', '=', $post->id)->get();
return view('single', compact('post','comments'));
with this i can basically load my post details and foreach that post comments (so far so good).
What I want to do
Is to get my comments by ajax, so for example when user 1 is reading the post and somewhere else user 2 add new comment user 1 see it imminently. So user 1 doesn't need to refresh the page to see the new comment.
Question
How can I do that?

You can use channels of Laravel combined to redis server. Each time you store a comment you can push to the post channel your comment and display it with ajax (use laravel echo server). All subscribed users to this channel will receive the new comment.

This is how I would do this
PHP
Route::get('/posts/{post}/comments', 'PostsController#comments');
public function post(Post $post) {
return response()->json(
Post::with('comments')->get() // Create HasMany relation named "comments", see Eloquent Relationships
);
}
Javascript
(function($) {
var intervalMiliseconds = 5000;
var pool = function() {
$.ajax({
method: 'GET',
url: '/post/100/comments',
success: function(response) {
console.log(response);
}
});
};
setInterval(pool, intervalMiliseconds);
})(jQuery);
Please avoid using PHP code in your javascript code, simply move all JS code to *.js files, and most if not all the required data from PHP pass by using data-* element attributes

Related

Laravel : How to add particular array store in session

I am little confused about session as i am new to in laravel. On my laravel app there is a lists of activity, every activity has it's details. When i click on activity button(button name: interesed?) activity id add on session, If i add another activity it is also add on session. I need functionality to add and remove inquiry id from session & on last i want all added activity id.
Note: I am doing using ajax.
What i have done sharing here.
Here is a view of my lists inquiry
On my web.php define a route
Route::get('addInquiryData','Front\PlanController#addInquiry')->name('addInquiryData');
On view view.blade define onclick function
onclick="addInquiry({{ $activity->id }})"
On my ajax call
function addInquiry(id) {
var activity_id = id;
if(activity_id)
{
$.ajax({
type:"GET",
url:"{{ route('addInquiryData') }}?activity_id="+activity_id,
success:function(res)
{
if(res)
{
// operation here
}
}
});
}
}
On my controller just define a function.
public function addInquiry(Request $request) {
dd($request->activity_id); // gt activity id here
}
How can i do this?
You may try this code
Store Your Activity Id value in variable
$activityId=$request->activity_id
You can add value in session like this
if(!Session::has('activity_'.$activityId)){
session(['activity_'.$activityId=>$activityId]);
}else{
session()->forget('activity_'.$activityId);
}
You can remove value in session like this
session()->forget('activity_'.$activityId);

simple json response with cakephp

I trying to pass some json to a controller in cakePHP 2.5 and returning it again just to make sure it is all going through fine.
However I getting no response content back. Just a 200 success. From reading the docs I am under the impression that if I pass some json then the responseHandler will the return json as the response.
Not sure what I am missing.
Data being passed
var neworderSer = $(this).sortable("serialize");
which gives
item[]=4&item[]=3&item[]=6&item[]=5&item[]=7
appController.php
public $components = array(
'DebugKit.Toolbar',
'Search.Prg',
'Session',
'Auth',
'Session',
'RequestHandler'
);
index.ctp
$.ajax({
url: "/btstadmin/pages/reorder",
type: "post",
dataType:"json",
data: neworderSer,
success: function(feedback) {
notify('Reordered pages');
},
error: function(e) {
notify('Reordered pages failed', {
status: 'error'
});
}
});
PagesController.php
public function reorder() {
$this->request->onlyAllow('ajax');
$data = $this->request->data;
$this->autoRender = false;
$this->set('_serialize', 'data');
}
UPDATE:
I have now added the following to the routes.php
Router::parseExtensions('json', 'xml');
and I have updated my controller to
$data = $this->request->data;
$this->set("status", "OK");
$this->set("message", "You are good");
$this->set("content", $data);
$this->set("_serialize", array("status", "message", "content"));
All now works perfectly.
A proper Accept header or an extension should to be supplied
In order for the request handler to be able to pick the correct view, you need to either send the appropriate Accept header (application/json), or supply an extension, in your case .json. And in order for extensions to be recognized at all, extension parsing needs to be enabled.
See http://book.cakephp.org/...views.html#enabling-data-views-in-your-application
The view only serializes view vars
The JSON view only auto-serializes view variables, and from the code you are showing it doesn't look like you'd ever set a view variable named data.
See http://book.cakephp.org/...views.html#using-data-views-with-the-serialize-key
The view needs to be rendered
You shouldn't disable auto rendering unless you have a good reason, and in your case also finally invoke Controller:render() manually. Currently your action will not even try to render anything at all.
CakeRequest::onlyAllow() is for HTTP methods
CakeRequest::onlyAllow() (which btw is deprecated as of CakePHP 2.5) is for specifying the allowed HTTP methods, ie GET, POST, PUT, etc. While using any of the available detectors like for example ajax will work, you probably shouldn't rely on it.
Long story short
Your reorder() method should look more like this:
public function reorder() {
if(!$this->request->is('ajax')) {
throw new BadRequestException();
}
$this->set('data', $this->request->data);
$this->set('_serialize', 'data');
}
And finally, in case you don't want/can't use the Accept header, you need to append the .json extension to the URL of the AJAX request:
url: "/btstadmin/pages/reorder.json"
and consequently enable extension parsing in your routes.php like:
Router::parseExtensions('json');
ps
See Cakephp REST API remove the necessity of .format for ways to use the JSON view without using extensions.
Output your json data
public function reorder() {
$this->request->onlyAllow('ajax');
$data = $this->request->data;
$this->autoRender = false;
$this->set('_serialize', 'data');
echo json_encode($data);
}

Maintaining Session through Angular.js

I am working a project using the AngularJS framework. I am pretty new to using this framework; in the past I have only worked with pure JavaScript and jQuery. The project is a kind of web designer application for a niche market.
As the user moves between pages while designing I want to maintain a session of all the changes they are making.
Now if the user signs in we load the session using data from the database. When the user clicks on save button we update the database with the session data. Someone told me that I can maintain session in Angular similar to backbone. Is this possible? If yes, can you please direct me to a tutorial that does not focus on directives or UI? If this is not possible are there other viable options?
Here is a kind of snippet for you:
app.factory('Session', function($http) {
var Session = {
data: {},
saveSession: function() { /* save session data to db */ },
updateSession: function() {
/* load data from db */
$http.get('session.json').then(function(r) { return Session.data = r.data;});
}
};
Session.updateSession();
return Session;
});
Here is Plunker example how you can use that:
http://plnkr.co/edit/Fg3uF4ukl5p88Z0AeQqU?p=preview
Because the answer is no longer valid with a more stable version of angular, I am posting a newer solution.
PHP Page: session.php
if (!isset($_SESSION))
{
session_start();
}
$_SESSION['variable'] = "hello world";
$sessions = array();
$sessions['variable'] = $_SESSION['variable'];
header('Content-Type: application/json');
echo json_encode($sessions);
Send back only the session variables you want in Angular not all of them don't want to expose more than what is needed.
JS All Together
var app = angular.module('StarterApp', []);
app.controller("AppCtrl", ['$rootScope', 'Session', function($rootScope, Session) {
Session.then(function(response){
$rootScope.session = response;
});
}]);
app.factory('Session', function($http) {
return $http.get('/session.php').then(function(result) {
return result.data;
});
});
Do a simple get to get sessions using a factory.
If you want to make it post to make the page not visible when you just go to it in the browser you can, I'm just simplifying it
Add the factory to the controller
I use rootScope because it is a session variable that I use throughout all my code.
HTML
Inside your html you can reference your session
<html ng-app="StarterApp">
<body ng-controller="AppCtrl">
{{ session.variable }}
</body>
You can also try to make service based on window.sessionStorage or window.localStorage to keep state information between page reloads. I use it in the web app which is partially made in AngularJS and page URL is changed in "the old way" for some parts of workflow. Web storage is supported even by IE8. Here is angular-webstorage for convenience.
You would use a service for that in Angular. A service is a function you register with Angular, and that functions job is to return an object which will live until the browser is closed/refreshed. So it's a good place to store state in, and to synchronize that state with the server asynchronously as that state changes.
Typically for a use case which involves a sequence of pages and in the final stage or page we post the data to the server. In this scenario we need to maintain the state. In the below snippet we maintain the state on the client side
As mentioned in the above post. The session is created using the factory recipe.
Client side session can be maintained using the value provider recipe as well.
Please refer to my post for the complete details.
session-tracking-in-angularjs
Let's take an example of a shopping cart which we need to maintain across various pages / angularjs controller.
In typical shopping cart we buy products on various product / category pages and keep updating the cart. Here are the steps.
Here we create the custom injectable service having a cart inside using the "value provider recipe".
'use strict';
function Cart() {
return {
'cartId': '',
'cartItem': []
};
}
// custom service maintains the cart along with its behavior to clear itself , create new , delete Item or update cart
app.value('sessionService', {
cart: new Cart(),
clear: function () {
this.cart = new Cart();
// mechanism to create the cart id
this.cart.cartId = 1;
},
save: function (session) {
this.cart = session.cart;
},
updateCart: function (productId, productQty) {
this.cart.cartItem.push({
'productId': productId,
'productQty': productQty
});
},
//deleteItem and other cart operations function goes here...
});

How to make an Ajax request in Joomla Component

This a screen shot of what I get when I call my ajax request:
How do I run only the task, without printing the whole page? This is my ajax call:
$.ajax
({
type: "POST",
url: "index.php?option=com_similar&task=abc",
data: {
id: id,
name: name,
similar_id: similar_id,
},
cache: false,
success: function(html)
{
$("#flash").fadeOut("slow");
$("#content"+similar_id).html(html);
}
});
});
$(".close").click(function()
{
$("#votebox").slideUp("slow");
});
});
Don't go with exit or die, Joomla! has it's nice way of dealing with this stuff.
The answers below are tested in Joomla! 2.5 & 3 (for 1.5. may work as well).
General
Your URL for the task needs to look like this:
index.php?option=com_similar&task=abc&format=raw
You than create the controller which will use the view, let's say Abc, which will contain the file view.raw.html (identical to a normal view file).
Below you have the code for generate a raw HTML response:
/controller.php
public function abc()
{
// Set view
JRequest::setVar('view', 'Abc');
parent::display();
}
/views/abc/view.raw.php
<?php
defined('_JEXEC') or die;
jimport('joomla.application.component.view');
class SimilarViewAbc extends JView
{
function display($tpl = null)
{
parent::display($tpl);
}
}
/views/abc/tmpl/default.php
<?php
echo "Hello World from /views/abc/tmpl/default.php";
Note: This is the solution I would use if I had to return HTML (it's cleaner and follows Joomla logic). For returning simple JSON data, see below how to put everything in the controller.
If you make your Ajax request to a subcontroller, like:
index.php?option=com_similar&controller=abc&format=raw
Than your subcontroller name (for the raw view) needs to be abc.raw.php.
This means also that you will / may have 2 subcontrollers named Abc.
If you return JSON, it may make sense to use format=json and abc.json.php. In Joomla 2.5. I had some issues getting this option to work (somehow the output was corrupted), so I used raw.
If you need to generate a valid JSON response, check out the docs page Generating JSON output
// We assume that the whatver you do was a success.
$response = array("success" => true);
// You can also return something like:
$response = array("success" => false, "error"=> "Could not find ...");
// Get the document object.
$document = JFactory::getDocument();
// Set the MIME type for JSON output.
$document->setMimeEncoding('application/json');
// Change the suggested filename.
JResponse::setHeader('Content-Disposition','attachment;filename="result.json"');
echo json_encode($response);
You would generally put this code in the controller (you will call a model which will return the data you encode - a very common scenario). If you need to take it further, you can also create a JSON view (view.json.php), similar with the raw example.
Security
Now that the Ajax request is working, don't close the page yet. Read below.
Don't forget to check for request forgeries. JSession::checkToken() come in handy here. Read the documentation on How to add CSRF anti-spoofing to forms
Multilingual sites
It may happen that if you don't send the language name in the request, Joomla won't translate the language strings you want.
Consider appending somehow the lang param to your request (like &lang=de).
New in Joomla 3.2! - Joomla! Ajax Interface
Joomla now provides a lightweight way to handle Ajax request in a plugin or module. You may want to use the Joomla! Ajax Interface if you don't have already a component or if you need to make requests from a module your already have.
If you just want to include the response output in some HTML element, append format=raw to your URL as mentioned above. Then you could have a controller function like this:
function abc(){
//... handle the request, read variables, whatever
print "this is what I want to place in my html";
}
The AJAX response will output everything you printed / echoed in the controller.

How do I use RequestHandler to accept data from ajax?

I try to send data form ajax to cakephp cotroller
function loadtooltip(obj, $user_id) {
//AJAX
var req = Inint_AJAX();
req.onreadystatechange = function () {
if (req.readyState==4) {
if (req.status==200) {
displaytooltip(obj, req.responseText);
}
}
};
req.open("POST", "http://127.0.0.1/cakeplate/tooltips/tooltip/", true);
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
req.send($user_id);
};
this controller
<?php
Class TooltipsController extends AppController{
var $name = 'Tooltips';
var $uses = array('Reply','User');
var $component = array('RequestHandler','Javascript','Ajax');
var $layout = 'tooltip';
function tooltip($user_id=NULL){
if(!empty($user_id)){
$tooltip = $this->Reply->User->findById($user_id);
$this->set('tooltip',$tooltip);
}
}
}
?>
I need somebody to help me to modified code
the way you're doing at the moment in the controller, you won't me able to get the user_id, because it is a var passed through GET method of http.
This variable would be accessible if you make a GET request for example for this url:
http://example.com/cakeplate/tooltips/tooltip/1 where 1 would be your $user_id.
If you send the request as POST, you can access the values in this var $this->data
This way you will be able to process the request based in the var that you pass to the controller.
Another problem that you will face that this controller will need to render a view, so i suggest that you take a look at http://book.cakephp.org/view/1238/REST, there you can see how you can create a route that will make the controller parse another view, it a different custom layout, like the json (the one i suggest in this case), and then you can show in this view only the json value.
Last, but important as well, i would suggest to that you use jQuery to do the javascript part, i think it will be easier, you can check it at http://api.jquery.com/jQuery.get

Resources