Home > OS >  Save unique visitor's ip and timestamp only in Laravel
Save unique visitor's ip and timestamp only in Laravel

Time:01-15

My application will save users' IPs and timestamps once they visit a specific page.

if (! auth()->check()) {
        $attributes = [
            'type' => 'Visited',
            'description' => 'The proposal was recently visited by someone with IP address '.\request()->getClientIp(),
            'ip' => \request()->getClientIp()
        ];

        (new ProposalLogController())->store($proposal, $attributes);
    }

Here's how I store all the details with IPs:

public function store($proposal, $attributes)
{
    $proposalLog = new ProposalLog();
    $proposalLog->proposal_id       = $proposal->id;
    $proposalLog->event_type        = $attributes['type'];
    $proposalLog->event_description = $attributes['description'];
    $proposalLog->ip_address        = $attributes['ip'];
    $proposalLog->user_name         = $attributes['user']??'';
    $proposalLog->save();
}

When a user reloaded or refreshed the page, it happened to save the same IP and timestamp again. What is the best way to prevent committing the same IP address, timestamp, or any laravel specific function that handles this issue?

CodePudding user response:

One way would be to use unique validation rules to prevent saving duplicate IP addresses and timestamps.

$validatedData = request()->validate([
    'ip' => 'unique:proposal_logs,ip_address',
    'created_at' => 'unique:proposal_logs,created_at'
]);

CodePudding user response:

Here we go, you can utilize the request validator and the rule of unique to accomplish this by doing the following:

Add this to the top of the controller:

use Illuminate\Validation\Rule;

Modify your store function: make sure to change the your_table_here with your table name.

public function store($proposal, $attributes)
{
    $validator = \Validator::make($attributes, [
        'ip_address' => [
            'required',
            Rule::unique('your_table_here')->where(function ($query) use($attributes) {
                return $query->where(['ip_address' => $attributes['ip_address'], 
                                      'user_name' => $attributes['user_name']]);
            }),
        ], 
    ]);
        
    if ($validator->fails()){
        //You can return whatever view, or just simply ignore this, you can use it for now for testing.
        return 'ip address exists for the user.';
    }else {
        $proposalLog = new ProposalLog();
        $proposalLog->proposal_id       = $proposal->id;
        $proposalLog->event_type        = $attributes['type'];
        $proposalLog->event_description = $attributes['description'];
        $proposalLog->ip_address        = $attributes['ip'];
        $proposalLog->user_name         = $attributes['user']??'';
        $proposalLog->save();
    } 
}

The above will basically do the following query on validation:

SELECT
  count(*) AS aggregate
FROM
  `your_table_name`
WHERE
  `ip_address` = 127.0.0.1
  AND (
    (
      `ip_address` = 127.0.0.1
      AND `user_name` = abcd
    )
  )
  • Related