Store views in background into the table - laravel

I want to save comments, posts and profiles that a user views in a viewable table. Posts and comments are displayed in a stream similar to social networks. How can I store the data in a viewable table in the background?
Table:
viewables
user_id
viewable_id
viewable_type
For example, if a user views or sees a post in the stream, the database should store the user_id and post_id. The same should be possible with comments and profiles.
EDIT:
The posts are issued in a forelse loop and the comments in a foreach.
#forelse ($posts as $post)
#if ($post->type === 1)
{{$post->body}}
#foreach ($post->comments as $comment)
{!!$comment->body!!}
#endforeach
#elseif ($post->type === 2)
{{$post->image}}
#foreach ($post->comments as $comment)
{!!$comment->body!!}
#endforeach
#elseif ($post->type === 3)
show post with type 3
#elseif ($post->type === 4)
show post with type 4
#else
show remaining
#endforelse

Based on your edit, there are a few different ways to handle this. Technically, since all posts are included on the page, it could be assumed that the user has read them all and simply save the user id for all of the posts loaded before rending the view.
If you wanted something more refined, however, you could use an ajax method to post the user id, post id, etc. when scrolling over it, though I don't find that very practical, as that could cause problems if someone scrolls through too fast.
The best option (without requiring user interaction) would be to load a couple posts at a time. Either automatically when scrolling (see this answer), or with the help of Laravel's pagination (https://laravel.com/docs/5.7/pagination) and set the user id when loading the data.
Example:
$posts = Posts::paginate(5);
foreach($posts as $p) {
DB::table('viewables')->insert([
'user_id' => $user->id,
'viewble_id' => $p->id,
`viewable_type` => $p->type,
]);
}

Related

change color base on status name in laravel

I have post table in my laravel the table has status this name in the field, approved decline so I will like that in my blade view components when a post is approved I want give it a green background and when a post is decline I will like it to be red
so in my loop I have this
#foreach($posts as $post )
{$post->body}
{$post->status}
#endforeach
add
bg-green
class to markup when your post->status is approved and add
bg-red
when post->status is declined

laravel 5.5 multiple controller inside one view

How to show TeamController#index and ProductController#index both show list of team and product inside one view main.blade.php
Looks like you want to show two datasets on one page. Basically, it means you have to execute two controller methods but it's not necessary to follow each and everything that official documentation says.
For example, if Products belong to a team, you can execute only TeamController#index and show products as given below.
#foreach($teams as $team)
#foreach($team->products as $product)
{{ $product->name }}
#endforeach
#endforeach
If no teams and products are two different entities and does not have any relation, you can just pass teams and products like this:
TeamController.php
public function index()
{
$teams = Team::all();
$products = Product::all(); // Don't forget to include 'use App\Product'
return view('index',compact(['teams','products']);
}
and then you can show teams and products like this:
index.blade.php
#foreach($teams as $team)
{{ $team->name }}
#endforeach
#foreach($products as $product)
{{ $product->name }}
#endforeach
Getting information from two different models does not mean you have to execute two different controller functions.
Still, if you want to get data from two different controllers, you can setup index.blade.php and create two ajax requests that will get data from two different URLs (two different controller methods).
Let me know if you have any more questions.
You can't show results from two controllers like that. Create a view that includes both the view that TeamController#index and ProductController#index return. be aware that both might be extending a layout which will probably try to load your page twice, so keep in mind to split the views into smaller components and include only those.
More info here
https://laravel.com/docs/5.6/views#creating-views

Notification not working on Multiple guards

I have 2 guards. One 'user' and the other 'admin'.
I have stored notification in database as admin. But guard('admin') is not working.
Here is my code in blade file:
<span class="badge badge-light">{{count(auth()->guard('admin')->user()->unreadNotifications())}}</span>
But i am only getting '1' as a result. I have 6 records in my table. Also my forech loop is not working either with guard. Here is the code:
<ul class="dropdown-menu">
#foreach(auth()->guard('admin')->user()->notifications() as $notifications)
<li>{{$notifications->type}}</li>
#endforeach
</ul>
Thanks a bunch
Try using notifications and unreadNotifications without ()
auth()->guard('admin')->user()->notifications
//
auth()->guard('admin')->user()->unreadNotifications
When using () on relationships you are always retrieving a Eloquent or Query Builder instance

Does Laravel Auth::user()->name and Auth::user()->email do two querys

I have a blade view for logged in users
To display my users name and email I do this
<p>{{ Auth::user()->name }}</p><br>
<p>{{ Auth::user()->email }}</p>
But what happens in the backround?
Does Laravel do two querys? One to fetch the users name and one to fetch the email?
I just wonder if I should contionue to do like the above code or just fetch alla data in need in the controller with one query.
It will do only one query. To remind my self of this I usually stick the user in the route and pass to the blade template:
$user = Auth:user();
return view('yourview', ['user' => $user]);
Then in blade you can use:
<p>{{$user->id}}</p>
<p>{{$user->name}}</p>
<p>{{$user->email}}</p>
Either way is fine i just find this way cleaner.
If you want to see all the queries your app runs when you visit a page check out Laravel Debugbar
Laravel Debugbar

Laravel 4 - Update Div Using Ajax

I'm using Laravel 4 and am trying to update a (#articles) div with the new articles that are retrieved from an ajax request. When I inspect the page and view the Network section, I can see the POST requests being fired off and it's not showing any errors (eg, articles appear to be returned). However, unfortunately, the #articles div is not being updated with the new information. Yet, if I do a browser refresh, the new articles are displayed.
Routes.php
Route::any("/dashboard/latest_sa", [
"as" => "dashboard/latest_sa",
"uses" => "DashboardController#latest_sa"
]);
controllers/DashboardController.php
Class DashboardController extends \BaseController
{
...
protected function latest_sa()
{
if( Request::ajax() )
{
// called via ajax
$articles = Articles::orderBy('published_at', 'desc')->paginate(20);
return json_decode($articles);
}
else
{
// fresh page load
$articles = Articles::orderBy('published_at', 'desc')->paginate(20);
return $articles;
}
}
...
}
app/views/dashboard/default.blade.php
...
#section("content")
// defined in /public/js/main.js
<script type="text/javascript">
callServer();
</script>
<div class="col-xs-4 col-sm-4 col-md-4 col-lg-4">
<h4>Latest Articles</h4>
<div class="articles">
<ul>
#foreach ($articles as $article)
<li>
<img src="{{ $article->user_image }}" alt="{{ $article->article_title }}" />
{{ $article->article_title }}
<div class="details">
<span class="author">{{ $article->author_name }}</span>
<span class="created">{{ Helpers::time_ago($article->published_at) }}</span>
<span class="symbol">{{ $article->symbol_title }}</span>
</div>
</li>
#endforeach
</ul>
</div>
{{ $articles->links() }}
</div>
...
/public/js/main.js
function callServer()
{
setInterval(function(){
$.ajax({
type: "POST",
url: "dashboard/latest_sa",
success:function(articles)
{
$(".articles").html(articles);
}
});
},5000);
}
JS is hardly my strong suit, so I'm not sure what I'm doing wrong here.
And, for clarity sake, the reason why I'm trying to update all of the articles in the div is so that the Helpers::time_ago method also gets called, instead of just fetching the new articles. This way, it properly shows how long ago the article was published (eg, less than a minute ago, a minute ago, a hour ago, a day ago, etc) without refreshing the page. Essentially, I'm trying to kill two birds with one stone; update the div with the most recent articles, and update the remaining article's published_at attribute using my Helpers::time_ago method. If there is a more effective / efficient way of doing this, feel free to correct me. This seems rather crude, but since it's only for personal use and will never be used for commercial purposes, it suits my needs (not that that excuses bad code).
Nonetheless, from my fairly basic understanding, the JS should be doing the following steps:
1) Fire a POST request off to the /dashboard/latest_sa route
2) Execute the DashboardController#latest_sa action
3) Return a DB collection of all $articles ordered by the latest published date, and paginated
4) Pass the $articles collection back to the JS success attribute (as articles)
5) Fire the anonymous function, with the articles collection as an argument
6) Update the corresponding inner HTML with the results from the articles collection
The logic sounds right, so I'm pretty sure this is going to be a human error (98% of the time it is, after all. lol). Hopefully, someone here will be able to see the (probably glaring) problem in the logic and point me in the right direction.
In the meantime, I'm going to keep toying around with it.
I look forward to your thoughts, ideas, and suggestions. TIA.
EDIT:
Well, I found one of the problems; the articles div is a class, and in the JS I'm referring to it as an id. I fixed that, and now after the timeInterval, the article's div is "updated" but no results are being displayed (none, zippo, nadda).
Yet, if I directly access the /dashboard/latest_sa URI I get the valid JSON response that I'm expecting. So, albeit I am closer, I am still missing something.
EDIT 2:
Okay, in the controller, I made some changes which can be seen above, where I am now doing a json_decode on the $articles, before returning them to be passed into the view. With that in place, the articles are showing back up again after the timeInterval has elapsed, however, the new articles and the published_at for the existing articles are not being updated. After reviewing Inspect -> Network, it shows that the server is responding with a 500 Internal Server Error from the ajax POST request.
Hrm... Seems like I'm going in circles. Sounds like a good time to take a break and go for a walk. ;)
EDIT 3:
Well, I modified my Helpers class and added in the following method to check if the $article is a json object.
public static function isJson($string)
{
json_decode($string);
return (json_last_error() == JSON_ERROR_NONE);
}
app/views/dashboard/index.blade.php
#foreach ($articles as $article)
<?php
if( Helpers::isJson($article) )
{
$article = json_decode($article);
// dd($article) // when uncommented it returns a valid PHP object
}
?>
<!-- Iterate over the article object and output the data as shown above... -->
#endforeach
As you can see, (for the time being) inside of my view's foreach($articles as $article), I run Helpers::isJson($article) as a test and decode the object if it is json. This has enabled me to get passed the 500 Internal Server Error message, populate the articles div with the results on the initial load, and after the ajax POST request is fired off, I'm getting back a server response of 200 OK according to Inspect -> Network. However, after it updates the div, it doesn't show any articles.
Around, and around I go... I think it's time I take that break I keep murmuring about. ;)
Any thoughts, suggestions and / or ideas are greatly welcomed and appreciated.
At first, you should know that, when you return a collection from the controller/route, the response automatically turns in to a json response so, you don't need to use json_decode() and it won't work, instead, you may try something like this (from your controller for ajax):
$articles = Articles::orderBy('published_at', 'desc')->paginate(20);
return View::make('defaultAjax')->with('articles', $articles);
Since building the HTML in the client side using the json data received from server side would be tough for you so, you may return HTML from the server with the generated view instead of json, so you may try something like this in your success handler:
success:function(articles) {
$(".articles").html(articles);
}
Now create a view for ajax response without extending the template like this:
//defaultAjax.blade.php used in the controller for ajax response
<ul>
#foreach ($articles as $article)
<li>
<img src="{{ $article->user_image }}" alt="{{ $article->article_title }}" />
{{ $article->article_title }}
<div class="details">
<span class="author">{{ $article->author_name }}</span>
<span class="created">{{ Helpers::time_ago($article->published_at) }}</span>
<span class="symbol">{{ $article->symbol_title }}</span>
</div>
</li>
#endforeach
</ul>
{{ $articles->links() }}
Notice, there is no #extendds() or #section(), just plain partial view, so it'll be rendered without the template and you can insert the ul inside the .articles div. That's it.
$("#articles").html(articles); ->> $(".articles").html(articles);

Resources