How to implement "show more" in Laravel - php

I want to display a certain number of records from the database on the page. However, when I click the "show more" button, it displays all the records.
#foreach ($spec as $item)
#continue($item->id == 1)
{{ $item->title }}
<div class="spec__item-lang">
{{ $item->lang }}
</div>
#break($item->id == 7)
#endforeach
<button class="spec__btn">See more</button>
public function index()
{
$spec = Qualifications::simplePaginate(6);
return view('spec', compact('spec'));
}

You can create a custom pagination. And
public function index(Request $request)
{
if($request->has('type'){
if($request->type=='all'){
$spec = Qualifications::all(6);
}
}else{
$spec = Qualifications::simplePaginate(6);
}
return view('spec', compact('spec'));
}

Related

Display primary video for specific ad/property in Laravel

I am working on a project for ads/properties in Laravel. I have gallery of multiple videos for each individual ad. I want to be able to select one of those videos with radio button and make it primary video for that ad (show that particular video next to ad). I have has many relationship between property and video. I am trying to update my is_main_video column to be 1 if it is main or 0 if it isn't and then display that video if it is 1 in my view. I am having trouble to write that method in my controller I get success message but my is_main_video column remains null. Any help is appreciated. Here are my tables and code.
properties (id, title, location, price)
videos (id, filename_video, model_id, is_main_video)
In videos table model_id column is foreign key that connects to properties table.
PropertyController.php
public function update(StorePropertyInfo $request, Property $property, Video $video)
{
$videoExtensions = ['mp4', '3gp', 'wmv', 'flv', 'avi'];
$image_arr = array_filter(explode(',', $request->image), 'strlen');
foreach ($image_arr as $key => $value) {
$file = explode('.', $value);
ext = end($file);
if (in_array($ext, $videoExtensions)) {
$query = Property::query();
if ($request->has('radio')) {
$request->get('radio');
}
if ($request->radio) {
$query->whereHas('videos', function ($query) use ($request) {
$query->where('is_main_video', 'like', '%' . $request->radio . '%');
});
}
$data = $query;
$video->where('filename_video', $value)
->update([
'model_id' => $property->id,
'is_main_video' => $data
]);
};
$request->validated();
return redirect()
->back()
->with('message', 'Property information updated');
}
}
edit.blade.php
<input type="hidden" id="hideninput" data-src="property/{{$property->id}}/gallery"value="{{old('video',$video)}}" name="video">
#if (old('video', $video))
#foreach (array_filter(explode(',',old('video', $video)), 'strlen') as $key =>$value)
<div id="{{'div_video_'.$key}}" class="col-md-3" style="padding: 15px;">
<input type="radio" name="radio" value="radio">Make main
<button data="{{$key}}" type="button" class="closebuttonvideo">
<span aria-hidden="true">×</span>
</button>
<video name="video" id="{{'video_'.$key}}" data={{$value}} src="/storage/property/{{$property->id}}/gallery/{{$value}}" class="video-js vjs-default-skin" controls preload="auto" data-setup='{"inactivityTimeout": 0}' width="180" height="180"></video>
</div>
#endforeach
#endif
videos table migration
public function up()
{
Schema::table('videos', function (Blueprint $table) {
$table->boolean('is_main_video')->nullable()->default(null);
$table->unique(['model_id', 'is_main_video']);
});
}
Property.php
protected $appends = ['is_main_video'];
public function videos()
{
return $this->hasMany(Video::class, 'model_id');
}
Video.php
public function properties()
{
return $this->belongsTo(Property::class);
}
I would do a partial rewrite, something like this:
PropertyController.php in edit(); Retrieving a property with attached videos.
return view('edit', [
'property' => Property::with('videos')->find(1),
]);
edit.blade.php
#foreach($property->videos as $video)
<input type="radio" name="main_video" value="{{ $video->id }}">Video {{ $video->id }}<br>
#endforeach
PropertyController.php in update(); Toggle the is_main_video attribute of each video of the property.
foreach ($property->videos as $video) {
$video->is_main_video = ($video->id == $request->input('main_video'));
$video->save();
}

Troubles with getting sub-categories of main category in Laravel

I'm trying to learn Laravel while writing some common features. Now what I'm trying to make is when I click on main category link to open new page and display all sub-categories assigned to this category. Sounds pretty simple but I can't display them.
This is what I have in my Category Model
public function parent()
{
return $this->belongsTo('App\Category', 'parent_id');
}
public function children()
{
return $this->hasMany('App\Category', 'parent_id');
}
And in controller
public function categoryListing( $category_id )
{
$categories = Category::with('children')->get();
$category = Category::find($category_id);
if($category->parent_id == 0) {
$ids = Category::select('id')->where('parent_id', '!=',0)->get();
$array = array();
foreach ($ids as $id) {
$array[] = (int) $id->id;
}
} else {
$items = Item::where('category_id' ,$category_id)->paginate(5);
}
return view('category_list', compact('categories','items'));
}
The idea here is to display Main Category and all sub-categories (childs) of this main category.
And this is the loop on the page
#foreach($categories as $category)
<a href="{!!route('list',array($category->id))!!}">
<span><strong>{!!$category->title!!}</strong> ({!! $category->itemCount!!})</span>
</a>
<ul class="list-group">
#foreach($category as $subcategory)
{!!$subcategory->title!!}
<span class="badge badge-primary badge-pill">{!! $subcategory->itemCount !!}</span>
</li>
#endforeach
</ul>
#endforeach
Current error is
Trying to get property of non-object
on the inside foreach.
Just try this is 'cleaner'.. if it works, start adding your links and other content so you will know what does not work.
#foreach($categories as $category)
<span><strong>{!!$category->title!!}</strong></span>
<ul class="list-group">
#foreach($category as $subcategory)
<li>{!!$subcategory->title!!}</li>
#endforeach
</ul>
#endforeach
Make sure the variables you try to print exist in each object.
You can try to dd($categories); in your controller before the return view('category_list', compact('categories','items')); statement to see whats inside $categories

Updating database with laravel

Let me explain situation, person is searching through skills and when clicked displays list of handymans with that skill, when user clicks on one of them, full details are displayed. user then clicks assign job link and is taken to a page with jobs along with checkbox and when desired job is chosen, and submit button clicked, I want a database to update "job_id" value in "handymen" database. How could that be done?
#extends('layouts.master')
#section('title', 'Assign Job')
#section('content')
#section('content')
<form action="{{url('assignjob')}}" method="POST">
{{ csrf_field() }}
#foreach ($jobs as $job)
<div>
<label>{{$job->name}}</label>
<input type='checkbox' value='{{$job->id}}' name='jobs[]'/>
</div>
#endforeach
<input type="submit" name="submitBtn" value="Assign Job">
</form>
#endsection
function search()
{
$skills = Skill::all();
return view('layouts/search',['skills' => $skills]);
}
function details($skillId)
{
$skill = Skill::find($skillId);
$handymen = $skill->handymen;
return view('layouts/details', ['skill' => $skill,'handymen' => $handymen]);
}
function assignJob($handymanId)
{
$assignJob = Hadnyman::find($handymanId);
$jobs = Job::all();
return view('layouts/assignjob',['jobs' => $jobs]);
}
function jobassign(Request $request)
{
return redirect('assignjob');
}
function skilledHandyman($handymanId)
{
$skilledHandyman = Handyman::find($handymanId);
return view('layouts/skilledHandyman', ['skilledHandyman' => $skilledHandyman]);
}
If a specific code is needed, please let me know
You should look at Eloquent Relationship.
Handymen has many Job
class Handymen extends Model {
...
public function jobs() {
return $this->hasMany(App\Job::class);
}
}
In your controller
function assignJob(Request $request, $id)
{
$handymen = Handyman::findOrFail($id);
// $request->get('jobs') = [1, 6, 7, etc...]
$handymen->saveMany($request->get('jobs'));
return ...;
}

simplify this #foreach/if in blade and laravel

I am fairly new to laravel (L5 specifically) and I am making my own version of a todo app rather than following one of the tutorials out there. I've learned quite a bit so far but the way I have this piece of code currently laid out in my blade template makes me think their might be a simpler way of doing this.
My TodosController#index fn is
public function index()
{
$todos = Todo::get();
return view('todos', compact('todos'));
}
App\Todo extends an Eloquent model which makes data handling very easy!
My route is:
Route::bind('todos', function($slug)
{
return App\Todo::whereSlug($slug)->first();
});
So my page simply displays an unorded list of "todos". I want to have two separate lists. One that is for completed todos and one for incomplete. My blade template looks like this so far and looks a bit messy. Also I am looping over the results twice which is where I think I can improve on.
<h3>Incomplete</h3>
<ul>
#foreach ($todos as $todo)
#if ($todo->completed == 'No')
<li>
{{ $todo->title }}
</li>
#endif
#endforeach
</ul>
<h3>Complete</h3>
<ul>
#foreach ($todos as $todo)
#if ($todo->completed == 'Yes')
<li>
{{ $todo->title }}
</li>
#endif
#endforeach
</ul>
Any suggestions to simplify that blade template?
DRY your code out. You could streamline it by moving the actual item mark-up to a partial template since it’s repeated in both the complete and incomplete lists:
<h3>Incomplete</h3>
<ul>
#foreach ($todos as $todo)
#if ($todo->completed == 'No')
#include('partials.items.todo')
#endif
#endforeach
</ul>
<h3>Complete</h3>
<ul>
#foreach ($todos as $todo)
#if ($todo->completed == 'Yes')
#include('partials.items.todo')
#endif
#endforeach
</ul>
And partials.items.todo would look like this:
<li>
{{ $todo->title }}
</li>
I would also re-factor your loops. Instead of looping over the same list twice, you could split them in your controller:
public function index()
{
$todos = Todo::where('user_id', '=', Auth::id())->get();
$complete = $todos->filter(function ($item) {
return $item->completed = 'Yes';
});
$incomplete = $todos->filter(function ($item) {
return $item->completed = 'No';
});
return view('todos', compact('complete', 'incomplete'));
}
Looking at your Todo model, I’d also make your completed column in the database a boolean field instead of a column containing “Yes” or “No” strings. You could then cast that column value to a proper boolean (since MySQL doesn’t have a native boolean field type):
class Todo extends Model
{
protected $casts = [
'completed' => 'boolean',
];
public function isComplete()
{
return $this->completed;
}
}
And then re-factor your controller action to use this instead:
public function index()
{
$todos = Todo::where('user_id', '=', Auth::id())->get();
$complete = $todos->filter(function ($item) {
return $item->isComplete() === true;
});
$incomplete = $todos->filter(function ($item) {
return $item->isComplete() === false;
});
return view('todos', compact('complete', 'incomplete'));
}
You could even move those collection filters to a custom TodoCollection class:
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
class TodoCollection extends EloquentCollection
{
public function complete()
{
return $this->filter(function ($item) {
return $item->isComplete() === true;
});
}
public function incomplete()
{
return $this->filter(function ($item) {
return $item->isComplete() === false;
});
}
}
Sorry for the lengthy reply, but should give you food for though on how to re-factor your code.
Only a bit simplified but...
You can try in your controller:
public function index()
{
$completed = Todo::where('completed','Yes')->get();
$incompleted = Todo::where('completed','No')->get();
return view('todos', compact('completed', 'incompleted'));
}
in Your template:
<h3>Incomplete</h3>
<ul>
#foreach ($incompleted as $todo)
<li>
{{ $todo->title }}
</li>
#endforeach
</ul>
<h3>Complete</h3>
<ul>
#foreach ($completed as $todo)
<li>
{{ $todo->title }}
</li>
#endforeach
</ul>
Another approach using a subtemplate like this:
//_list_todos.blade.php
#foreach ($todos as $todo)
<li>
{{ $todo->title }}
</li>
#endforeach
And your main template like this:
<h3>Incomplete</h3>
<ul>
#include('_list_todos',['todos'=>$incompleted] )
</ul>
<h3>Complete</h3>
<ul>
#include('_list_todos',['todos'=>$completed] )
</ul>
The advantege to use a subtemplate like the last one is you can reuse the code, and simplify your main templates.

Having trouble creating a Like system for comments in a Laravel Project

I'm creating a project using Laravel. Users are able to like comments. I want to display a "like" button so a user can like a comment and if the user has already liked the comment I want that button to be "unlike" so a user can unlike the liked comment
In my database I have a likes table:
| id | user_id | comment_id |
My Like Model looks like this:
class Like extends \Eloquent {
protected $fillable = ['user_id', 'comment_id'];
protected $table = 'likes';
public function owner()
{
return $this->belongsTo('Acme\Users\User', 'user_id');
}
}
Comment Model looks like this:
class Comment extends \Eloquent {
protected $fillable = ['user_id', 'post_id', 'body'];
protected $table = 'comments';
public function owner()
{
return $this->belongsTo('Acme\Users\User', 'user_id');
}
public function likes()
{
return $this->hasMany('Acme\Likes\Like');
}
}
User model:
class User extends Eloquent {
public function comments()
{
return $this->hasMany('Acme\Comments\Comment');
}
public function likes()
{
return $this->hasMany('Acme\Likes\Like');
}
}
Likes controller :
class LikesController extends \BaseController {
use CommanderTrait;
/**
* Like a comment
* #return Response
*/
public function commentLike()
{
// using a command bus. Basically making a post to the likes table assigning user_id and comment_id then redirect back
extract(Input::only('user_id', 'comment_id'));
$this->execute(new CommentLikeCommand($user_id, $comment_id));
return Redirect::back();
}
public function unlike()
{
$like = new Like;
$user = Auth::user();
$id = Input::only('comment_id');
$like->where('user_id', $user->id)->where('comment_id', $id)->first()->delete();
return Redirect::back();
}
}
In my view I'm able to get the comments via $comment, and I'm able to get likes via $comment->like have:
#foreach($post->comments as $comment)
<div class="user-comment">
<p class="comment">
{{ $comment->owner->first_name }} {{ $comment->owner->last_name }} {{ $comment->body }}
</p>
<div class="com-details">
<!-- how long ago the comment was posted -->
<div class="com-time-container">
{{ $comment->created_at->diffForHumans() }} ·
</div>
<!-- HERE IS WHERE I WANT THE LIKE AND UNLIKE BUTTONS TO DISPLAY -->
#if ($comment->likes->owner->id === $currentUser->id)
{{ Form::open(['route' => 'like']) }}
{{ Form::hidden('user_id', $currentUser->id) }}
{{ Form::hidden('comment_id', $comment->id) }}
<button type="submit" class="com-like">Like</button>
{{ Form::close() }}
#else
{{ Form::open(['route' => 'unlike']) }}
{{ Form::hidden('user_id', $currentUser->id) }}
{{ Form::hidden('comment_id', $comment->id) }}
<button type="submit" class="com-like">Unlike</button>
{{ Form::close() }}
#endif
<!-- how many users like this comment -->
<span class="likes"> · {{ $comment->likes->count() }}</span>
</div>
</div><!--user-comment end-->
#endforeach
Im trying to set up an if statement to see if the current user has liked the status but im not sure how this is done? If the user has not liked the comment yet I want the "like" button to display. If the user has liked the comment I want the "unlike" button to display. I thought I could say #if($comment->likes->owner->id === $currentUser->id) but I get Undefined property. How would I go about doing this?
$comment->likes is a Collection of Like objects. To access the owner property, you would need to iterate the collection.
However, another option is to use the available methods on the Collection to do what you need:
#if (in_array($currentUser->id, $comment->likes->lists('user_id')))
$comment->likes->lists('user_id') will return an array of all the user_id values in the Collection of Likes for the Comment. in_array() will check if the $currentUser->id is in that array.
I haven't worked much with Laravel, so my syntax and terminology might be a bit off, but it should be the right idea.
Basically, $comment->likes is a list of likes on that comment. You need to iterate through those likes and check if one of them is by the current user. If one of them is by the current user, then show the unlike button. Otherwise, show the like button.
Not sure what that'd look like in Blade, but here's some pseudo-code:
$currentUserLiked = false;
// go through all of the comment's likes
foreach ($comment->likes as $like)
{
// check if this like is by the current user
if ($like->owner->id == $currentUser->id)
{
$currentUserLiked = true;
break;
}
}
if ($currentUserLiked)
{
showUnlikeButton();
}
else
{
showLikeButton();
}

Categories