I am trying to implement user tracking in Laravel by writing statistics after user login. I.e, location, timezone and such. I sort of had a half luck of implementing it.
I used ajax by attaching event listener to submit button on login form. After the form is submitted, ajax method is called. This method gets user's stats by using an api call. Then that ajax request sends that data to StatsController@store
which then records that entry to stats table.
This only achieved by using e.preventDefault();
, if i don't use it, records are not inserted into db and it's throws an error which quickly vanishes after redirecting to dashboard.
Ajax method resides in js file which is being called in layout file.
Here is a ajax method:
function getCoords(){
return fetch('https://ipinfo.io/geo')
.then((response) => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
else{
return response.json();
}
})
.then((response) => {
let url = "/writeStats";
let token = document.querySelector("meta[name='csrf-token']").getAttribute("content");
let forma = document.getElementById("loginForm");
let formElements = {};
formElements.email = forma.elements[1].value;
formElements.password = forma.elements[2].value;
$.ajax({
url: url,
type: 'POST',
data: {_token: token , message: "bravo", stats: response, formElements: formElements},
dataType: 'JSON',
success: (response) => {
console.log("success");
console.log(response);
},
error: (response) => {
console.log("error");
console.log(response);
}
});
})
.catch((error) => {
console.error('There has been a problem with your fetch operation:', error);
});
}
window.addEventListener("click", (e) => {
if(e.target.id==="loginBtn"){
//e.preventDefault();
getCoords();
}
});
web.php:
Route::post('/writeStats','StatsController@store');
StatsController:
public function store(Request $request)
{
if($request->ajax()){
$email = $request->formElements["email"];
$password = $request->formElements["password"];
$user = DB::table('users')->where("email", "=", $email)->first();
if(Hash::check($password, $user->password)) {
$stat = new Stats;
$stat->ip = $request->stats["ip"];
$stat->city = $request->stats["city"];
$stat->region = $request->stats["region"];
$stat->country = $request->stats["country"];
$stat->coords = $request->stats["loc"];
$stat->timezone = $request->stats["timezone"];
$stat->user_id = $user->id;
$stat->save();
$response = array(
"message" => "bravo",
"request" => $request->all(),
"stats" => $request->stats,
"user" => $user,
"stat" => $stat,
);
return response()->json($response);
}
}
}
php artisan --version
shows Laravel Framework 6.9.0
My question is: How to insert into stats table just after user's logging?
Edit1:
I am now trying somewhat different approach. Instead of some custom method from StatsController, i am now using authenticated
method in LoginController.
public function authenticated(Request $request)
{
$credentials = $request->only('email', 'password');
$email = $request->input("email");
$password = $request->input("password");
$user = DB::table('users')->where("email", "=", $email)->first();
if (Auth::attempt($credentials)) {
$stat = new Stats;
$stat->ip = $request->stats["ip"];
$stat->city = $request->stats["city"];
$stat->region = $request->stats["region"];
$stat->country = $request->stats["country"];
$stat->coords = $request->stats["loc"];
$stat->timezone = $request->stats["timezone"];
$stat->user_id = auth()->user()->id;
$stat->save();
$response = array(
"stat" => $request->all(),
);
return redirect()->intended('dashboard');
}
}
and in web.php:
Route::post('/login','Auth\LoginController@authenticated');
Still no luck. I just don't know what approach to use. It feels so close, like i missing something small.
Edit2:
Let me rephrase question:
How to send api call response to login controller, so that after user is authenticated, i can insert api response data into another table(not users table)? Can i:
- Somehow insert api response into authenticate request?
- Or, how to authenticate while simultaneously writing records into table
stats
?
I tried both approaches(see: Original and Edits), but not sure what should i write...