$video->increment('total_clicks');
the increment() method takes in a column name and increments it by one.
https://laravel.com/docs/5.7/queries#increment-and-decrement
Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.
I have videos uploaded on my project I want to count the number of times it was clicked. Is there a way to do that?
$video->increment('total_clicks');
the increment() method takes in a column name and increments it by one.
https://laravel.com/docs/5.7/queries#increment-and-decrement
Sure, but it entirely depends on how you're currently doing things. How are people able to view these videos (I assume that's what you want counted is the views)? Is it going through a controller specifying the video id to show? If so, that would be the easiest as you know the video id, and you know someone requested it.
Thank you @wilburpowery for that I will check that out
@cronix When people click the video to play it will count as a view, also yes its going to a controller. How would I go about it?
yes its going to a controller
Typically you have a show() method to display something by the id.
public function show($video_id) {
Video::where('id', $video_id)->increment('counter_field');
// other stuff...send video to view, etc.
}
So just get the video by the id, and increment whatever field you're using to store the view count.
It depends on what your current method looks like, and whether you're using route model binding, etc. It would be helpful to see your method for displaying the video.
Like for route model binding, it would be more like
public function show(Video $video) {
$video->increment('counter_field');
// other stuff...send the video to the view, etc
}
@cronix so far this is is what I have in my view.
@foreach($pro as $proo)
<div class="panel panel-default" id="panel_mobile" style="border-radius:2%; border-top:none; border-left:none; border-right:none; padding-bottom:5%; ">
<video class="video1" id="cx" preload="auto" align="middle" data-toggle="modal" data-target="#mymodalproo{{$proo->id}}" style="
cursor:pointer; "><source src="{{$proo->video}}" playsinline alt="Video Unavailable" id="" ></source>
</video>
@enforeach
// on click video opens in Modal
@foreach($pro as $proo)
<div class="container">
<div class="row">
<div class="col-sm-12">
<div id="mymodalproo{{$proo->id}}" class="modal fade" role="dialog" style="padding-top:3%;">
<h1 class="close" data-dismiss="modal" style="color:white; position:relative; right:20px;">X</h1>
<div class="modal-dialog">
<!--modal content-->
<div class="modal-content" style="align-items: center;">
<div class="modal-body" style=" height:300px; width:100%; background:black;">
<video id="video" id="cb" preload="auto" align="middle" style="
cursor:pointer; "><source src="{{$proo->video}}#t=15" playsinline alt="Video Unavailable" id="" ></source>
</video>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@endforeach
Ok, so you're not just displaying a single video, you're displaying a bunch in the loop. So, this will be a bit harder to do since you're not using a controller to show a single video by its id.
I think the easiest thing to do would be to use ajax. Since your videos all use a class of video1, I'd set up a click event targeting that class that would retrieve the video id (you'd add a new data property on the video tag that would hold the id of the video) in the click event, fire off an ajax request to an endpoint that sends the video id, and then increment it for that id like was shown above. It's a bit more complex.
However, there's something else I'd do before tackling this feature. Currently you are generating a modal for every single video. That's not the best way to do that. You can have a single modal, and then pass data to it depending on what was clicked to open it.
It looks like you're using bootstrap, so here's how to do that. https://getbootstrap.com/docs/4.0/components/modal/#varying-modal-content
@Cronix ok, thank you I will try that most definitely. I will give you an update on this
Once you get a single modal working, you can actually just fire the ajax request from the show.bs.modal event instead of a click event targeting .video1. If you added a data-video-id="{{ $proo->id }}" to the buttons that open the modal
$('#exampleModal').on('show.bs.modal', function (event) {
var button = $(event.relatedTarget) // Button that triggered the modal
var video_id = button.data('video-id');
// fire off ajax request and send video_id
});
@Cronix ok,and I also want to make sure it dosen't refresh the page when I click
Nothing I've said would cause any refreshing, except for the content of the single modal when different videos are viewed.
@cronix Ok, thanks I will give you an update on this
Hey @Cronix I have an update for you. I think i'm like all over the place with this. I got the clicks to work I used the increment() method that @wilburpowery told me about, but everything is not quite working all the way. See, when I click on the video it does increment in the database which is what I wanted but its not doing it one by one. For example I will click on one of the videos and it will increment the count but it will also do it for the other video and I didn't click it I just clicked the other one. I will go ahead and show you my code. Correct me if I did anything wrong.
//Controller
public function show(){
$aaa=User::orderBy('created_at','desc')->get();
return view('layouts.ajax')->with('aaa',$aaa);
}
public function index(Request $request){
$the_id=$request->my_id;
$video=User::where('id','LIKE', '%'.$the_id.'%');
$video->increment('clicks');
$video->update();
$msg = "You clicked!.";
return response()->json(array('msg'=> $msg), 200);
}
//views
<body>
@if($aaa->count()>0)
@foreach($aaa as $a)
<div style="background:yellow;">
<video width="20%" style="height:auto;" data-toggle="modal" data-target="#mymodalproo{{$a->id}}">
<source src="{{$a->intro_video}}" type="">
</source>
</video>
<h5>video has {{$a->clicks}} views</h5>
</div>
@endforeach
@endif
@foreach($aaa as $a)
<div class="container">
<div class="row">
<div class="col-sm-12">
<div id="mymodalproo{{$a->id}}" class="modal fade" role="dialog" style="padding-top:3%;">
<h1 class="close" data-dismiss="modal" style="color:white; position:relative; right:20px;">X</h1>
<div class="modal-dialog">
<!--modal content-->
<div class="modal-content" style="align-items: center;">
<div class="modal-body" style=" height:300px; width:100%; background:black;">
<div style="background:yellow;">
<form action="" onclick="getMessage()" style="height:auto;">
<button><input type="text" name="my_id" value="{{$a->id}}" style=""></button>
<video width="40%" style="height:auto;">
<source src="{{$a->intro_video}}" type="">
</source>
<input type="submit" value="click">
</form>
</video>
<h5>video has {{$a->clicks}} views</h5>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@endforeach
</body>
<script>
function getMessage(){
$.ajax({
type:'get',
url:'getmsg',
data:'_token = <?php echo csrf_token() ?>',
success:function(data){
}
});
}
</script>
//Route
Route::get('ajax','AjaxController@show');
Route::get('getmsg','AjaxController@index');
I'm guessing because
$video=User::where('id','LIKE', '%'.$the_id.'%');
$video->increment('clicks');
You're using like, which can return more than one result. where id like %1% would return 1, 10, 101, 31... anything with a 1 in it.
It also looks like you're incrementing a count for a user, not a video.
@Cronix Thanks for replying... the user table has their video in there I just did it that way. Besides the where is Like% is there something else that you suggest I use?
No, I think you just need $video = User::where('id', $the_id)->increment('clicks'); You shouldn't have to update() it. increment() will do that.
@Cronix I switched it to
$video = User::where('id', $the_id)->increment('clicks');
but now the clicks dosen't increment
The only thing you're sending in your ajax is the _token field. You need to send my_id as well since that's what you're using in your query $the_id=$request->my_id;
One piece of advice I have in your coding career is to explicitly name variables. Not trying to be rude, but stuff like this is garbage: @foreach($aaa as $a). What is $aaa? It is a collection of users (plural). Name it $users in your controller, pass it as $users. When you iterate over something, you are iterating over many things. So name it plural. Then name the individual thing you're iterating over as singular, like foreach($users as $user). Then it's perfectly clear to you, and anybody, what is going on. Variables are cheap in languages. $youCanNameThemAsLongAsYouNeed. Name them for what they represent. Even though you are only interested in the users videos, it's still the User and not a Video object.
Look at how confusing this is.
@foreach($aaa as $a)
<button><input type="text" name="my_id" value="{{$a->id}}" style=""></button>
@endforeach
//...
$the_id=$request->my_id;
$video=User::where('id', $the_id);
You're using my_id and $the_id to represent the same thing, which is actually the User id. Name it for what it represents, $user_id.
@foreach($users as $user)
<button><input type="text" name="user_id" value="{{$user->id}}" style=""></button>
@endforeach
//...
$user_id=$request->user_id;
$video=User::where('id', $user_id);
Now it's consistent everywhere,and named for what it represents which makes the code clearer. Sorry to go off on a tangent. It's just an important aspect of coding. Clean, clear, concise code is a lot easier to work on and maintain in both the short and long term. It prevents bugs and saves time troubleshooting and your code reads more like documentation rather than a head scratcher trying to figure out how everything is flowing. Imagine a coworker, who has never seen the code before, trying to figure it out. Imagine yourself a year from now coming back to a project after not having worked on it. Would everything be clear to you, or would you have to waste time figuring it out because it's obfuscated?
@cronix Honestly I am not even mad at you for coming at me like that because you're right. I just name my variables like that for no reason at all I just name them any random crap and I understand it thats what I feel matters but my apologies. You didn't say anything wrong.
Hi @Cronix hope all is well, I took your advice and I renamed the variables so that You and I both can understand and its more clear. I am having this little issue. This is what I did, so I wrapped the video around a form because its going to act like a submit button. So whenever the user clicks on the video there submitting the form(which they don't know) and it is counted as a click and therefore it will be incremented in the database, now the form is being submitted without the page needing to refresh which is what I wanted. The problem is i have more than one video and say if I click the first video it will increment the click which is good but say if I click the second video it wont increment it but it will do it for he first one which is not what I'm looking for it supposed to be like a one by one thing. I hope you understand what I am trying to say here. Here is the code
<head>
<script>
$(document).ready(function(){
$(function(){
var ClosestDiv=$('#myform').closest('div');
$(this).submit(function(event){
event.preventDefault();
$.ajax({
method: 'GET',
url: 'getmsg',
dataType: "json",
contentType: "application/json",
data : $('#myform').serialize(),
success: function(data){
}
});
});
});
});
</script>
</head>
<body>
@if($user->count()>0)
@foreach($user as $users)
<div style="background:yellow;">
<video width="20%" style="height:auto;" data-toggle="modal" data-target="#mymodal{{$users->id}}">
<source src="{{$users->video}}">
</source>
</video>
<h5>video has {{$users->clicks}} views</h5>
</div>
@endforeach
@endif
@foreach($user as $users)
<div class="container">
<div class="row">
<div class="col-sm-12">
<div id="mymodal{{$users->id}}" class="modal fade" role="dialog" style="padding-top:3%;">
<h1 class="close" data-dismiss="modal" style="color:white; position:relative; right:20px;">X</h1>
<div class="modal-dialog">
<!--modal content-->
<div class="modal-content" style="align-items: center;">
<div class="modal-body" style=" height:300px; width:100%; background:black;">
<div style="background:yellow;">
<form id="myform">
<input type="text" name="request_id" value="{{$users->id}}"/>
<button type="submit" name="click" id="myform" style="background:none; border:none; outline:none;">
<video width="40%" style="height:auto;">
<source src="{{$users->video}}">
</source>
</video>
</button>
</form>
<!--<input type="submit" name="click" value="button" />-->
</form>
<h5>video has {{$users->clicks}} views</h5>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@endforeach
Your code changes are much better! The only thing is this is reversed @foreach($user as $users) should be @foreach($users as $user) and pass it as $users from the controller instead of $user.
You have a fundamental issue with your html/js, which I eluded to on the previous page where you are generating a modal for each individual video instead of reusing a single modal for all. This is causing issues due to the way you did that.
Id's in html need to be unique. No 2 tags between the <body></body> tags can share the same id. All of your forms have id of myform. Since id's are supposed to be unique, it only grabs the first element on the page with myform in var ClosestDiv=$('#myform').closest('div');
I'd urge you to use a single modal, and use the buttons that trigger opening the modal to vary the contents of the modal based on what button was clicked. That will save a LOT of html on your page and is the proper way to do this. As I mentioned, you can use the show.bs.modal event on the modal to vary the contents, and you can send your ajax request there as well. You wouldn't even need a form in the modal. You pass the data you need in the modal as data-* properties on the modal triggers, and then read them when the button was clicked.
https://getbootstrap.com/docs/4.0/components/modal/#varying-modal-content
It would be something like (I can't test this - and I did switch $user/$users so adjust your controller accordingly)
// generate the modal buttons, passing the video source and user id as data props
@foreach ($users as $user)
<div style="background:yellow;">
<video width="20%"
data-toggle="modal"
data-target="#mymodal"
data-user-id="{{$user->id}}"
data-video-src="{{$user->video}}"
data-video-views="{{$user->clicks}}"
>
<source src="{{$user->video}}"></source>
</video>
<h5>video has {{$user->clicks}} views</h5>
</div>
@endforeach
// generate the single modal that will be reused (no foreach)
// I stripped out everything but bare essentials for easier reading
// the only things that will change in here are the video source and "views". Those have id's to easily target
<div id="mymodal" class="modal fade" role="dialog">
<h1 class="close" data-dismiss="modal">X</h1>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<video width="40%" style="height:auto;">
<source id="video-source" src=""></source>
</video>
<h5>video has <span id="video-views"></span> views</h5>
</div>
</div>
</div>
</div>
// when a button opens the modal
$('#mymodal').on('show.bs.modal', function (event) {
// Button that triggered the modal
let button = $(event.relatedTarget);
// Extract info from data-* attributes on the button that was clicked
let user_id = button.data('user-id') ;
let video_src = button.data('video-src');
let video_views = button.data('video-views');
// set the video source attribute and "views" in the opened modal
let modal = $(this);
modal.find('#video-source').attr('src', video_src);
modal.find('#video-views').text(video_views);
// send ajax request to increment video count. Just send request_id
$.ajax({
method: 'GET',
url: 'getmsg',
dataType: "json",
contentType: "application/json",
data : {
request_id: user_id
},
success: function(data){
}
});
})
I can't guarantee that works 100% as is since I can't test it, but should be close. All we're doing is setting the data that needs to be passed to the modal on the trigger to open the modal, and then reading them once it was opened.
@cronix ok, thank you I will give you an update on how it works
@Cronix I just did everything you told me to do. It does open the modal and it just says "video has views" it doesn't show the video in the modal and also when I click it does nothing.
You'll have to play with it. Check the docs I linked to. It's hard for me to write all of the code out without having your data to actually test everything out and just write it off the top of my head in a textbox lol.
@cronix Okay sure no problem you're fine I will indeed play around with it. I really want to thank you because I didn't know about doing it this way and now things look more cleaner and not all over the place. Thanks!
@Cronix I've been playing around with this all day and I got nothing. The modal does not seem to be showing any content at all. I also looked at the link you showed me to see if I did everything correctly but I got nothing.
show all of the relevant code as you have it now. Both the Controller Method and View (with js)
@Cronix this is what I have
//The controller
public function show(){
$users=User::orderBy('created_at','desc')->get();
return view('layouts.ajax')->with('users',$users);
}
public function index(Request $request){
$requested_id=$request->input('request_id');
$video = User::where('id', $requested_id)->increment('clicks');
}
//Script
<script>
$('#mymodal').on('show.bs.modal', function (event) {
var button = $(event.relatedTarget);
var user_id = button.data('user-id') ;
var video_src = button.data('video-src');
var video_views = button.data('video-views');
var modal = $(this);
modal.find('#video_source').attr('src', video_src);
modal.find('#video_views').text(video_views);
$.ajax({
method: 'GET',
url: 'getmsg',
dataType: "json",
contentType: "application/json",
data : {
requested_id: user_id
},
success: function(data){
}
});
})
</script>
//html body
@foreach ($users as $user)
<div style="background:yellow;">
<video width="20%"
data-toggle="modal"
data-target="#mymodal"
data-user-id="{{$user->id}}"
data-video-src="{{$user->video}}"
data-video-views="{{$user->clicks}}"
>
<source src="{{$user->video}}"></source>
</video>
<h5>video has {{$user->clicks}} views</h5>
</div>
@endforeach
<div id="mymodal" class="modal fade" role="dialog">
<h1 class="close" data-dismiss="modal">X</h1>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<video width="40%" style="height:auto;">
<source id="video_source" src=""></source>
</video>
<h5>video has <span id="video_views"></span> views</h5>
</div>
</div>
</div>
</div>
Change the modal to
<div id="mymodal" class="modal fade" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">video has <span id="video_views"></span> views</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<video width="40%" style="height:auto;" id="video_source" src="">
</div>
</div>
</div>
</div>
The main thing that changed was putting the video src directly in the <video> tag instead of a separate <source> tag along with the video_source for the id. The other change was putting the video count in the title of the modal.
It was actually working the way it was (if you viewed the source code of the modal you could see the values changing), but due to the <source> being separate it wasn't triggering a video change so you couldn't see it.
Here's a working demo using the same structure for everything that you are, except for my additional changes (I also commented out the ajax request since this demo isn't on your server and instead dumped the video source and like count to console when opening the modal. https://jsfiddle.net/per2fnwg/
@Cronix Wow! this is crazy I just fixed it and the content is still not showing, and on top that I even copied and paste what you put on the JSFiddle and the content didn't show and I'm like wow even that didn't work and I see it working on JSfiddle. I made sure I have Bootstrap cdn and Jquery. I will show you what I did plus show you the bootstrap cdn and jquery.
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
<!-- jQuery library -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- Popper JS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
<!-- Latest compiled JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script>
<script>
$('#mymodal').on('show.bs.modal', function (event) {
var button = $(event.relatedTarget);
var user_id = button.data('user-id') ;
var video_src = button.data('video-src');
var video_views = button.data('video-views');
var modal = $(this);
modal.find('#video_source').attr('src', video_src);
modal.find('#video_views').text(video_views);
$.ajax({
method: 'GET',
url: 'getmsg',
dataType: "json",
contentType: "application/json",
data : {
requested_id: user_id
},
success: function(data){
}
});
})
</script>
</head>
<body>
@foreach ($users as $user)
<div style="background:yellow;">
<video width="20%"
data-toggle="modal"
data-target="#mymodal"
data-user-id="{{$user->id}}"
data-video-src="{{$user->video}}"
data-video-views="{{$user->clicks}}"
>
<source src="{{$user->video}}"></source>
</video>
<h5>video has {{$user->clicks}} views</h5>
</div>
@endforeach
<div id="mymodal" class="modal fade" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">video has <span id="video_views"></span> views</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<video width="40%" style="height:auto;" id="video_source" src="">
</div>
</div>
</div>
</div>
Please or to participate in this conversation.