简体   繁体   English

PHP mysqli带匿名连接的预准备语句

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM