Reputation: 579
I have a sql query that returns 5 closest locations using latitude & longitude.
$conn->query("SELECT activityId, ( 3959 * acos( cos( radians(
-0.0761144) ) * cos( radians(
activity.latitude ) ) * cos( radians(
activity.longitude ) - radians(
51.5080937) ) + sin( radians(
-0.0761144) ) * sin( radians(
activity.latitude ) ) ) ) AS distance
from activity order by distance limit 5;");
I need to make this a prepared statement, but to use the ? placeholder doesn't make sense as it would mean binding the same param twice. Oh and it doesn't actually work.
$stmt = $conn->prepare("SELECT activityId, ( 3959 * acos( cos( radians(
?) ) * cos( radians(
activity.latitude ) ) * cos( radians(
activity.longitude ) - radians(
?) ) + sin( radians(
?) ) * sin( radians(
activity.latitude ) ) ) ) AS distance
from activity order by distance limit 5;");
$stmt = $conn->prepare("ddd", $lat, $lng, $lat);
So I've done a little research and from what I can gather using a variable in the mysql statement seems the best approach, but this is where i get stuck, so far I have as follows.
$stmt = $conn->prepare("
set @lat = ?;
set @lng = ?;
SELECT activityId, ( 3959 * acos( cos( radians(
@lat) ) * cos( radians(
activity.latitude ) ) * cos( radians(
activity.longitude ) - radians(
@lng) ) + sin( radians(
@lat) ) * sin( radians(
activity.latitude ) ) ) ) AS distance
from activity order by distance limit 5;
");
$stmt->bind_param("dd", $lat, $lng");
However now the params don't bind and I get a error response back stating this. I've had a look on google and the answer I have been directed towards consists of running two queries, the font creating the variables as just a query() then then SELECT statement in a second prepared statement. But surely then the statements are not being prepared and leaves the query open to SQL Injection?
Is there a better way to prepare this statement so it's secure from injection attacks?
//* EDIT *//
After some great answers it seems that using set @var isn't valid in $sql->prepare(); I guess I can now refine the question to be; How can I run this as a prepared statement?:
$stmt = $conn->prepare("SELECT activityId, ( 3959 * acos( cos( radians(
?) ) * cos( radians(
activity.latitude ) ) * cos( radians(
activity.longitude ) - radians(
?) ) + sin( radians(
?) ) * sin( radians(
activity.latitude ) ) ) ) AS distance
from activity order by distance limit 5;");
$stmt = $conn->prepare("ddd", $lat, $lng, $lat);
Upvotes: 1
Views: 609
Reputation: 45500
Here is the proper way:
$stmt = $conn->prepare("SELECT activityId, ( 3959 * acos( cos( radians(
?) ) * cos( radians(
activity.latitude ) ) * cos( radians(
activity.longitude ) - radians(
?) ) + sin( radians(
?) ) * sin( radians(
activity.latitude ) ) ) ) AS distance
from activity order by distance limit 5;");
$stmt->bind_param("ddd", $lat, $lng, $lat);
$result = $stmt->execute();
if($result){
echo 'SELECT succesful';
}
Upvotes: 1
Reputation: 4937
Maybe you could try setting the type to double?
$stmt->bind_param("dd", $lat, $lng);
Upvotes: 0