[英]PHP mysqli Prepared Statement with anonymous join
I am currently frustrated with preparing one statement - culprit is not preparing it properly, but staying inline with my current function to bin a query with a variable number of parameters. 我目前对准备一个语句感到沮丧-罪魁祸首没有正确地准备它,而是与我当前的函数保持内联,以便对具有可变数量参数的查询进行装箱。 It works in all cases, but this query gives me an unsolveable problem (in one single query) for mysql:
它在所有情况下都有效,但是此查询给我一个针对mysql的无法解决的问题(在一个查询中):
SELECT studios.name,
studios.phone,
locations.zip_code,
locations.location_name,
addresses.street_name,
addresses.stree_nr,
persons.first_name,
persons.last_name,
p.distance_unit
* DEGREES(ACOS(COS(RADIANS(p.latpoint))
* COS(RADIANS(addresses.geo_lat))
* COS(RADIANS(p.longpoint) - RADIANS(addresses.geo_long ))
+ SIN(RADIANS(p.latpoint))
* SIN(RADIANS(addresses.geo_lat)))) AS distance
FROM studios
JOIN ( /* these are the query parameters */
SELECT ? AS latpoint, ? AS longpoint,
? AS radius, 111.045 AS distance_unit
) AS p ON 1=1
CROSS JOIN addresses
ON studios.address = addresses.id
CROSS JOIN locations
ON addresses.location = locations.id
CROSS JOIN persons
ON studios.owner = persons.id
CROSS JOIN studio_types
ON studios.studio_type = studio_types.id
WHERE addresses.geo_lat
BETWEEN p.latpoint - (p.radius / p.distance_unit)
AND p.latpoint + (p.radius / p.distance_unit)
AND addresses.geo_long
BETWEEN p.longpoint - (p.radius / (p.distance_unit * COS(RADIANS(p.latpoint))))
AND p.longpoint + (p.radius / (p.distance_unit * COS(RADIANS(p.latpoint))))
ORDER BY distance
LIMIT 25
The query itself is fully functional - here is a gist of it: 查询本身功能齐全-这是要点:
SELECT *
FROM studios
JOIN ( SELECT ? AS latpoint, ? AS longpoint,
? AS radius, 111.045 AS distance_unit
) AS p ON 1=1
now binding it is pretty straight forward: 现在绑定很简单:
$query = $this->conn->prepare($query);
if(!$query) throw new Exception($this->conn->error);
$query->bind_params("ddd", $val1, $val2, $val2);
$query->execute();
$query->get_result();
The error that occures by preparing already happens in the first line: Unknown column 'p.latpoint' in 'field list'
通过准备发生的错误已经在第一行中发生:
Unknown column 'p.latpoint' in 'field list'
Now this is a huge problem. 现在,这是一个巨大的问题。 Going around that would probably work with preparing statements with
SET @variable = ?
解决该问题可能与使用
SET @variable = ?
- but thats not a preferred situation, as it would break up my current scheme of dispatching my requests. -但这不是优选的情况,因为它会破坏我当前的分配请求的方案。
Is there any oversight or is this simply not possible, due to undefined joins while preparing? 由于准备时未定义的联接,是否存在监督或根本就不可能做到这一点?
Edit: third method would involve replacing the join and placing values - this would make a very confusuing amount of bind parameters - which would be hard to maintain later. 编辑:第三种方法将涉及替换联接和放置值-这将使非常混乱的绑定参数数量-以后很难维护。
So, I finally come around for anyone who seeks the same answer like me and I gotta extend where I left with it: 所以,我终于找到了像我一样寻求相同答案的人,我必须继续扩展下去:
Imagine a class that does all the heavy lifting for you, minimizing issues provides you a simple interface between you and your database. 想象一下一个类,它为您完成了所有繁重的工作,最大程度地减少了问题,从而为您提供了与数据库之间的简单接口。 There is a method that takes a statement string, type binding and like this:
有一个采用语句字符串,类型绑定的方法,如下所示:
protected function __dispatch($query, $types, $arguments) {
error_reporting(0);
$query = $this->conn->prepare($query);
if(!$query) throw new Exception($this->conn->error);
if($types !== "") call_user_func_array(array(&$query, 'bind_param'),
array_merge(array($types), $arguments));
$query->execute();
return $query->get_result();
}
Since placeholders cannot possibly any identifiers (thanks Jon), I can however bind SQL variables just fine. 由于占位符不可能包含任何标识符(感谢Jon),因此我可以很好地绑定SQL变量。 Then I am going to execute something like this:
然后,我将执行以下操作:
SELECT *
FROM studios
JOIN ( SELECT @lat AS latpoint, @lon AS longpoint,
@dist AS radius, 111.045 AS distance_unit
) AS p ON 1=1
This gives the possibility to bind variables before - and then use it in the statement, just like this: 这样就可以在-之前绑定变量,然后在语句中使用它,如下所示:
public function search_in_range($lat, $long, $distance) {
$this->__dispatch("SET @lat = ?", "d", array(&$lat));
$this->__dispatch("SET @lon = ?", "d", array(&$long));
$this->__dispatch("SET @dist = ?", "d", array(&$distance));
// And finally:
return $this->__dispatch($query, $types, [])->fetch_all();
}
This does the trick to create to have a very simple join with an anonymous set of data and use it in a more complicated statement later on. 这样做的技巧是创建一个非常简单的联接,并与一组匿名数据连接,然后在以后的更复杂的语句中使用它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.