what i am trying to do is getting my tvserious and movies from categories class
this is my categories class :
class Category extends Model
{
public function movies()
{
return $this->hasMany(Movie::class);
}
public function tvserious()
{
return $this->hasMany(Tvserious::class);
}
what i tried and it's working
public function CategoryClick($slug){
$media = Category::where('slugid',$slug)->with(['movies' => function($query) {
$query->whereNotNull('title');
},'tvserious' => function($query) {
$query->whereNotNull('title');
}])->inRandomOrder()->paginate(8);
return view('test')->with([
'catclick'=>$media,
'title'=>$slug,
]);
}
the problem with this way is in my blade i have to create a loop for movies and tvserious and the tvserious data will always stay at the end at it will show after the movies loop ends
#foreach($catclick as $media)
#foreach($media->movies as $movie )
{{ $movie->title }}
#endforeach
#foreach($media->tvserious as $tvserious )
{{ $tvserious->title }}
#endforeach
#endforeach
so how can i get both of my movies and serious in my blade mixed together
i don't want all the movies to be at first so where is the problem and how can i fix this ?
this worked pretty well for me ... #first
i made an accessor in my category class
public function getMediaAttribute()
{
return $this->movies->values()->toBase()
->merge($this->tvserious->values())
->sortByDesc(function ($media, $key) {
return $media->updated_at;
});
}
then in my controller
this is my controller function
use Illuminate\Pagination\LengthAwarePaginator as Paginator;
public function CategoryClick($slug){
$all = Category::where('slugid',$slug)->first()->getMediaAttribute(); // calling the accessor
// Then use following code to paginate the results:
$perPage = 10;
$currentPage = app('request')->get('page') ?: 1; // or $request->get('page') if available
$paginator = new Paginator($all, $all->count(), $perPage, $currentPage);
return (dd($paginator));
everything is great now thx for everyone who helped me to solve thix issue :D
Add an accessor to your Category model:
class Category
{
public function getMediaAttribute()
{
return $this->movies->values()->toBase()
->merge($this->tvserious->values())
->sortByDesc(function ($media, $key) {
return $media->updated_at;
});
}
}
Here we used a base collection instead of the Eloquent collection due to merge issues with the Eloquent collection (it does not allow for duplicate keys, thanks #lagbox for pointing it out). After merging both media types together, we also sort the resulting list based on their last update. This means recently touched entries will be listed first.
The newly created list can be accessed with $category->media. Instead of sortByDesc($func) also a simple sortBy('column') or shuffle() (to get a random order) would work.
You can use this code
#php
$moviesCount = $media->movies->count();
$tvseriousCount = $media->tvserious->count();
$maxCount = ($tvseriousCount > $moviesCount) ? $tvseriousCount : $moviesCount;
#endphp
#for ($index = 0; $index < $maxCount; $index++)
#isset($media->movies[$index])
{{ $media->movies[$index]->title }}
#endisset
#isset($media->tvserious[$index])
{{ $media->tvserious[$index]->title }}
#endisset
#endfor
Related
i was wondering of how can i show how many items i got in the cart? I did a path in the twig but im not sure how to show it.
this is my controller i have the route and in the twig i call the path with the name (count_panier).
/**
* #Route("/count/{qtt}", name="count_panier")
*/
public function testAction($qtt,Request $req)
{
$qtt = $this->afficherCount($req);
return $this->redirectToRoute('mag',['count'=>$qtt]);
}
//----------------------------------------------
public function afficherCount(Request $req){
$sess = $req->getSession();
$panier = $sess->get('panier',[]);
$qtt = 0;
foreach($panier as $item)
{
$qtt += $item->quantiteCommandee;
}
return $qtt;
}
And this is my twig, this is the part of the top navbar
<div class="menu">
<a class="active" href="{{path('mag')}}">Catalogue</a>
Contact
Crée un compte
Connexion
<a href="panier">Panier
<img width="30" alt="img" src="{{asset('images/cart.png')}}"/></a>
<span id='panierCompteur'>
items</span>
</div>
in your Controller you are passing just one parametere count => '$qtt
So in the Twig file, if you want get it, do this:
{{ count }}
So if you want to get a link that shows how many items you have, do like this:
<span id='panierCompteur'>
{{count}}
items</span>
(you are not usign the $qtt variable so don't pass it)
/**
* #Route("/count", name="count_panier")
*/
public function testAction(Request $req)
{
$qtt = $this->afficherCount($req);
return $this->redirectToRoute('mag',['count'=>$qtt]);
}
//----------------------------------------------
private function afficherCount(Request $req){
$sess = $req->getSession();
$panier = $sess->get('panier',[]);
$qtt = 0;
foreach($panier as $item)
{
$qtt += $item->quantiteCommandee;
}
return $qtt;
}
Of course the first time you render this main page you need to run the function afficherCount() in the index Controller (or whatever is your main controller) and return to the main page the count => '$qtt with all your others arguments.
You are redirecting to another route, so you need to "handle" the redirection if you want to get those parameters:
/**
* #Route("/your-route/{count?}", name="mag", requirements={"count"="\d+"})
*/
public function yourFunction(Request $req, $count)
{
// true if is the first time you render this page or if you don't pass the value
if($count === null){
$count = afficherCount($req);
}
return $this->Render('yourTwigFile.html.twig',['count'=>$count]);
}
{count?} : the ? if for optional parameters so the first time you render this page is not necessary to pass the value in the URL
requirements={"count"="\d+"} : the value can only be an integer
(PS. this function is probably your index)
for more information / examples
I use octobercms and User Extended plugin(Clacke). I try to render a pagination because for now i have a lot of registered users and they display on one page.
I use random users function from \classes\UserManager.php
public static function getRandomUserSet($limit = 7)
{
$returner = new Collection;
$userCount = User::all()->count();
if(!isset($userCount) || empty($userCount) || $userCount == 0)
return [];
if($userCount < $limit)
$limit = $userCount;
$users = User::all(); //paginate(5)
if(empty($users))
return $returner;
$users->random($limit);
$friends = FriendsManager::getAllFriends();
foreach($users as $user)
{
$userAdd = true;
if(!$friends->isEmpty())
{
foreach($friends as $friend)
{
if($user->id == $friend->id)
{
$userAdd = false;
break;
}
}
}
if($user->id == UserUtil::getLoggedInUser()->id)
$userAdd = false;
if($userAdd)
{
$returner->push($user);
}
}
return $returner->shuffle();
}
try to do this with changing return $returner->paginate(25); and $users = User::paginate(25); but throws me an error
An exception has been thrown during the rendering of a template
("Method paginate does not exist.").
After that i try to change directly in \components\User.php
public function randomUsers()
{
return UserManager::getRandomUserSet($this->property('maxItems'))->paginate(12);
}
But again the same error.
Tryed and with this code and render in default.htm {{ tests.render|raw }}
public function randomUsers()
{
$test = UserManager::getRandomUserSet($this->property('maxItems'));
return $test->paginate(10);
}
Again with no success. Could anyoune give me some navigation and help to fix this?
If you are using random users function from \classes\UserManager.php
I checked the code and found that its using Illuminate\Support\Collection Object. So, for that Collection Object pagination works differently
You need to use forPage method.
On the other hands paginate is method of Illuminate\Database\Eloquent\Collection <- so both collection are not same
Use forpage
// OLD return UserManager::getRandomUserSet($this->property('maxItems'))
// ->paginate(12);
TO
return UserManager::getRandomUserSet($this->property('maxItems'))
->forPage(1, 12);
forPage method works like forPage(<<PAGE_NO>>, <<NO_OF_ITEM_PER_PAGE>>);
so if you use forPage it will work fine.
if any doubt please comment.
I'm trying to fetch values at view passed from controller.
In my controller my syntax are:
public function index()
{
$vehicles=vehicles::orderBy('created_at', 'desc')->get();
// return $vehicles;
$ad=ads::orderBy('views','desc')->get();
// return $ad;
foreach ($ad as $ads) {
# code...
$popularvehicle[]=vehicles::where('id',$ads->id)->get();
// echo $popularvehicle;
}
return view('index',compact('vehicles','popularvehicle'));
}
In my views i've tried following:
#foreach($popularvehicle as $popularvehicle)
{{$popularvehicle->vname}}
#endforeach
It gives an error of Undefined property: Illuminate\Database\Eloquent\Collection::$vname
I've also tried {!!$popularvehicle['vname']!!}. But it throws error like undefined index.
When i echo {!!$popularvehicle!!} it gives all the values required like [{"id":3,"vname":"Pulsar","lotno":"Ba 25 Pa","engine":"150","mileage":"35","kilometers":25000,"price":"120000","negotiable":"Yes","vcondition":"New","used":"3 month","manufacture_year":"2015","description":"Almost New","Company_cid":1,"Users_id":1,"Vehicle_Type_id":1,"created_at":"2017-01-12 15:08:41","updated_at":"2017-01-12 15:08:41"}].
How can i fetch the values of $popularvehicle? Can anyone help me? Will converting array to object help solve this problem. If yes, how can i do so?
The error is because -> is trying to point to the property of object $popularvehicles[] is an array:
$ads=ads::orderBy('views','desc')->get();
foreach ($ads as $ad) {
$popularvehicles[]=vehicles::where('id',$ad->id)->get()->toArray();
}
and then,
#foreach($popularvehicles as $popularvehicle)
#foreach($popularvehicle as $vehicle)
{{$vehicle['vname']}}
#endforeach
#endforeach
Note the changes made for naming conventions. Also, Model name is good to be singular.
Consider plural name
$popularvehicles = array();
foreach ($ad as $ads) {
$popularvehicles[]=vehicles::where('id',$ads->id)->get();
}
return view('index',compact('vehicles','popularvehicles'));
And use in view
#foreach($popularvehicles as $popularvehicle)
{{$popularvehicle->vname}}
#endforeach
Try this:
Controller:
$popularvehicle = vehicles::where('id',$ads->id)->get();
// If you use $popularvehicles[] then you have to use one extra foreach() to retrieve the columns
View:
#foreach($popularvehicle as $vehicle)
{{$vehicle->id}} // for id
{{$vehicle->vname}} // for name
#endforeach
Try this:
public function index()
{
$vehicles = vehicles::orderBy('created_at', 'desc')->get();
// return $vehicles;
$ads = ads::orderBy('views','desc')->get();
// return $ad;
foreach ($ads as $ad) {
# code...
$popularvehicles[]=vehicles::find($ad->id);
}
return view('index',compact('vehicles','popularvehicles'));
}
And in your view:
#foreach($popularvehicles as $popularvehicle)
{{$popularvehicle->vname}}
#endforeach
I want to implement a system in my project that "alerts" users when there is a new comment on one of their posts.
I currently query all comments on the posts from the logged in user and put everything in an array and send it to my view.
Now my goal is to make an alert icon or something when there is a new item in this array. It doesn't have to be live with ajax just on page load is already good :)
So I've made a function in my UsersController where I get the comments here's my code
public function getProfileNotifications()
{
$uid = Auth::user()->id;
$projects = User::find($uid)->projects;
//comments
if (!empty($projects)) {
foreach ($projects as $project) {
$comments_collection[] = $project->comments;
}
}
if (!empty($comments_collection)) {
$comments = array_collapse($comments_collection);
foreach($comments as $com)
{
if ($com->from_user != Auth::user()->id) {
$ofdate = $com->created_at;
$commentdate = date("d M", strtotime($ofdate));
$comarr[] = array(
'date' => $ofdate,
$commentdate,User::find($com->from_user)->name,
User::find($com->from_user)->email,
Project::find($com->on_projects)->title,
$com->on_projects,
$com->body,
Project::find($com->on_projects)->file_name,
User::find($com->from_user)->file_name
);
}
}
} else {
$comarr = "";
}
}
Is there a way I can check on page load if there are new items in the array? Like keep a count and then do a new count and subtract the previous count from the new one?
Is this even a good way to apprach this?
Many thanks in advance! Any help is appreciated.
EDIT
so I added a field unread to my table and I try to count the number of unreads in my comments array like this:
$uid = Auth::user()->id;
$projects = User::find($uid)->projects;
//comments
if (!empty($projects)) {
foreach ($projects as $project) {
$comments_collection[] = $project->comments;
}
}
$unreads = $comments_collection->where('unread', 1);
dd($unreads->count());
But i get this error:
Call to a member function where() on array
Anyone any idea how I can fix this?
The "standard" way of doing this is to track whether the comment owner has "read" the comment. You can do that fairly easily by adding a "unread" (or something equivalent) flag.
When you build your models, you should define all their relationships so that stuff like this becomes relatively easy.
If you do not have relationships, you need to define something like the following:
In User
public function projects()
{
return $this->hasMany('App\Models\Project');
}
In Project
public function comments()
{
return $this->hasMany('App\Models\Comment');
}
Once you hav ethose relationshipt, you can do the following. Add filtering as you see fit.
$count = $user->projects()
->comments()
->where('unread', true)
->count();
This is then the number you display to the user. When they perform an action you think means they've acknowledged the comment, you dispatch an asynchronous request to mark the comment as read. A REST-ish way to do this might look something like the following:
Javascript, using JQuery:
jQuery.ajax( '/users/{userId}/projects/{projectId}/comments/{commentId}', {
method: 'patch'
dataType: 'json',
data: {
'unread': false
}
})
PHP, in patch method:
$comment = Comment::find($commentId);
$comment->update($patchData);
Keep in mind you can use Laravel's RESTful Resource Controllers to provide this behavior.
try this
$unreads = $project->comments()->where('unread', 1);
dd($unreads->count());
EDIT
My be Has Many Through relation will fit your needs
User.php
public function comments()
{
return $this->hasManyTrough('App\Project', 'App\Comment');
}
Project.php
public function comments()
{
return $this->hasMany('App\Comment');
}
then you can access comments from user directly
$user->comments()->where('unread', 1)->count();
or I recommend you define hasUnreadComments method in User
public function hasUnreadComments()
{
$return (bool) $this->comments()->where('unread', 1)->count();
}
P.S.
$uid = Auth::user()->id;
$projects = User::find($uid)->projects;
this code is horrible, this way much better
$projects = Auth::user()->projects;
I have a form that contains a list of settings, all with their own IDs, shown via simple foreach loop. When the user clicks the update button, I want to be able to update all of the values using Anahkiasen/Former. However, I can't seem to find the documentation on how to submit more than one set of records.
For instance, if I was opening the form to edit just one setting instead of all of them, I would just do the following:
{{ Former::open()->method('PUT')->action(URL::to('settings/' . $setting['id'])) }}
This would send it to my 'update' resource method and the following code would take care of the update:
public function update($id)
{
$setting = Setting::findOrFail($id);
if ($setting->save()) {
return Redirect::back()->with('message', "Setting #$id updated!");
} else {
return Redirect::back()->withInput()->withErrors($setting->errors());
}
}
Is it possible to do this with multiple records at once and still use the convenient $autoHydrateEntityFromInput and $forceEntityHydrationFromInput features?
I'm using Laravel 4.1 and Former 3.4.2.
This had to be done by just putting the values into an array and forcing the existing value in the Blade template:
#foreach ($settings as $s)
<div class="row">
{{ Former::text('values[' . $s['id'] . ']', $s['name'])->forceValue($s['value']) }}
</div>
#endforeach
Then retrieve the values in the controller:
public function update()
{
$values = Input::get('values');
foreach ($values as $id => $val) {
$setting = Setting::findOrFail($id);
$setting['value'] = $val;
if (!$setting->save()) {
return Redirect::back()->withInput()->withErrors($setting->errors());
}
}
return Redirect::back()->with('message', "Settings updated!");
}
Doing it this way, a standard resource won't work like Route::resource('settings', 'SettingsController'); so instead I had to simply do Route::post('settings/update', 'SettingsController#update');
As far as I can tell, auto hydration also won't work in this case.