Laravel 8 - count clicks but user can't spam the function - laravel

In my website I track clicks on a specific link and save the count on database with this function:
public function redirect($url)
{
$data = Class::where('url', $url)->first('clicks');
$cnt = $data->clicks;
$cnt++;
$sql = Class::where('url', $url)->update([
'clicks' => $cnt,
]);
if (!$sql) {
abort(500);
}
return redirect('https://website.com/'.$url);
}
the problem is if someone spam the link , the count goes up. I want stop count if user clicked on link 5mins ago.
he will redirected to the link but count doesn't go up.
I'm new so it's so good if you explain it with details. Thanks

I would create a new table, lets call it link_clicks. You will need 3 columns, one to identify the person, one to get the time and one to identify the link (I dont exactly know how you store the links you want to observe).
So more or less you will have the following table:
link_clicks
user_id
link_id
created_at
If the users are always logged in, I would store the user_id, if they are not logged in, I would store the IP-address. So instead of user_id make a column called ip or ip-address.
Afterwards you can easily get the last click and its time.
--Example
Your new table contains following entry:
user_id = 1, link_id = 1 and created_at = 2021-04-21 19:00:00
Now in your controller you get the current date_time date("Y-m-d H:i:s") and the user id like that: auth()->id(). You can also define your time treshold in minutes e.g max_dif = 5.
Afterwards you can query the table for all clicks for the user. You can either make the time comparision in your where() statement or you can make some comaprison in your php code to check if the time treshhold is reached.

Related

Remove duplicates from groupBy

I would like to find out how many Users have Swipes per day without duplicates of user_id within group.
So if a User has swiped multiple times on a day, I want the User only show once per group (per day). I am not really interested in the actual Swipes but rather in the swipe count per day.
I tried:
Swipe::all()->groupBy(function($item){ return $item->created_at->format('d-M-y'); })->unique('user_id')
To remove duplicate data, you can use unique().
I create an example for you.
I have dummy data like
.
So you want the result is data grouped by created_at and on every date return how many users swipe it but without duplicate user?
The code should be like:
$collect = Swipe::all()->groupBy(function($data){
return $item->created_at->format('d-M-y');
})->transform(function($dataGrouped,$date){
return [
$date => $dataGrouped->unique('user_id')
];
});
The result will be like:

Laravel, how to delete all records but the first one of that day

So I have a table to log profile followers every 10 minutes to keep a record of the increase/decrease.
However after the current day I only need to keep the last record of that day. Is there a simple way in Laravel to delete all records a part from the last one recorded every day.
I've tried searching and searching but comes up with nothing and feel like I'm going to create something overly complicated to accomplish this.
You'd need a query like this.
DELETE
FROM logs
WHERE id IN (
SELECT id
FROM logs
WHERE created_at BETWEEN 2022-02-28 00:00:00 AND 2022-02-28 23:59:59
ORDER BY created_at DESC
OFFSET 1
)
Assuming you have a date variable, you could make the query like this using the whereDate method:
$date = '2022-02-28'; // Y-m-d format. This is important.
DB::table('logs')
->whereIn('id', function ($sub) use ($date) {
$sub->select('id')
->from('logs')
->whereDate('created_at', $date)
->orderByDesc('created_at')
->offset(1);
})
->delete();

How to find the user with priority in laravel

I have a user table in laravel app.
I want to find a random user with the lowest number of loan_limit.
Right now I have this.
$random_user = User::inRandomOrder()
->where('loan_limit', '<=', 5)
->first();
But I want to find a random user with the minimum no. Of loan_limit like if a user has a loan_limit of 0, that user will get picked first, and if a user has 1, that user will be selected next, and finally if a user has a limit of 5, then that user will have less probability of getting picked.
you can get all the users with min loan_limit value, then take random one:
$random_user = User::whereRaw('loan_limit= (select min(`loan_limit`) from users)')
->get()->random();

Laravel get row with records above and below it

I have a Laravel 4.2 project where I get data from a SQL DB and I can display onto the page. I can select the single record just fine, but I want to also show the records around the one selected.
For example, I want to show the 5 records above and below the one selected. Im not sure how to do this in Laravel.
$gradschoolrange = MOGRadschool::where('Title', '=', $gradschool)->get();
In the above example $gradschool might be "Test College", it will return that with a value, but I want to show all the other related records around it with those values too. The results should look something like this:
ABC College
Another College
Blah College
Go To College
Test College
Yet Another College
Yo Yo College
College College
Something College
Eating College
As there's no ordering specified in your initial query, I'm assuming you want 5 next/previous records according to primary key (id? - if not, you would obviously need to change that) in the table?
Given that IDs may not be numerically sequential, we can't simply assume that the previous 5 rows will be the ID of the row with title = $gradschool minus 5, so wondered if this might work:
$initial = MOGRadschool::where('Title', $gradschool)->first(); // get the initial row with the title of $gradschool
$result = MOGRadschool::where('id', '<', $initial->id)->take(5)->orderBy('id', 'DESC') // new query getting the previous 5 rows, by ID
->union(MOGRadschool::where('id', '>', $initial->id)->take(5)) // union a second query getting the next 5 rows by ID
->get() // get the result as a collection
->add($initial) // add the initial row to the collection
->sort(); // sort the collection (by id) so that the initial row is in the middle
So the output is a collection containing the initial row in the middle, with up to 5 records either side. You also have the initial row to highlight the output, if you need that.
If you want it based on the IDs, which is what I understand from your issue, something like this should work:
$selectedGradSchool = MOGRadschool::where('Title', '=', $gradschool)->get()->first();
$aboveSelected = MOGRadschool::where('id', '<=', $selectedGradSchool->id)
->orderBy('id', 'desc')
->take('5')
->get();
$belowSelected = MOGRadschool::where('id', '>' $selectedgradSchool->id)
->take('5')
->get();
//Concatenate both results
$schoolRange = $aboveSelected->concat($belowSelected);
Now the collection should look similar to your desired result.

Xeroizer::ApiException : QueryParseException: No property or field 'inv_id' exists

I am Trying to get all the invoices in a single API hit.
Because, for every user having 100's of invoices.
It will exceed the API limit (Minute Limit: 60 calls in a rolling 60 second window).
I am trying to store all the invoice id into a single array and from that i will get the details of the user and then i loop the records locally and display it. It's the right way?
invoice_ids = user.estimates.select("invoice_id") || [] xero = Xeroizer::PrivateApplication.new(XERO_CONFIG["key"], XERO_CONFIG["secret"], XERO_CONFIG["path"], :rate_limit_sleep => 5)
invoices = ['795f789b-5958-xxxx-yyyy-48436dbe7757','987g389b-5958-xxxx-yyyy-68636dbe5589']
inv_id = invoice_ids.pluck(:invoice_id)
invoices = xero.Invoice.all(:where => 'InvoiceID==inv_id')
Also, I am getting the following error:
Xeroizer::ApiException (QueryParseException: No property or field 'inv_id' exists in type 'Invoice')
Looks like the problem is that you're not interpolating the inv_ids correctly. You probably need to do something like this:
invoices = xero.Invoice.all(:where => "InvoiceID==\"#{inv_id}\"")
You may have to perform some additional formatting on the inv_id variable to make it a valid Xero string. https://github.com/waynerobinson/xeroizer#retrieving-data

Resources