Doctrine - 如何将数组绑定到SQL?

时间:2016-05-13 12:07:29

标签: php pdo doctrine-orm symfony

我的SQL看起来像这样:

+"vert sbn"

但它返回:

  

执行(...)

时发生异常      用params   [[1,2,3,4,5,6,7,8,11,12,13,14],“拒绝”]

     

注意:数组转换为字符串

我无法使用$sql = "select * from user where id in (:userId) and status = :status"; $em = $this->getEntityManager(); $stmt = $em->getConnection()->prepare($sql); $stmt->bindValue(':userId', $accounts, \Doctrine\DBAL\Connection::PARAM_INT_ARRAY); $stmt->bindValue(':status', 'declined'); $stmt->execute(); $result = $stmt->fetchAll(); 因为我的真实SQL更复杂(例如包含连接的选择,联合等等)

3 个答案:

答案 0 :(得分:12)

您不能将预准备语句与数组一起使用,因为sql本身不支持数组。这是一个真正的耻辱。沿着这条线的某个地方,您实际需要确定您的数据是否包含三个项并发出一个IN(?,?,?)。 Doctrine ORM实体经理会自动为您完成此任务。

幸运的是,DBAL让您满意。你只是不使用绑定或准备。该手册有一个例子:http://doctrine-orm.readthedocs.io/projects/doctrine-dbal/en/latest/reference/data-retrieval-and-manipulation.html#list-of-parameters-conversion

在你的情况下,它看起来像:

$sql = "select * from user where id in (?) and status = ?";
$values = [$accounts,'declined'];
$types = [Connection::PARAM_INT_ARRAY, \PDO::PARAM_STR];
$stmt = $conn->executeQuery($sql,$values,$types);
$result = $stmt->fetchAll();

以上代码未经测试,但您应该明白这一点。 (请确保use Doctrine\DBAL\Connection;} {/ 1> Connection::PARAM_INT_ARRAY

使用命名参数的人注意:

如果使用命名参数(:param而不是?),则在提供类型时应尊重参数名称。例如:

$sql = "select * from user where id in (:accounts) and status = :status";
$values = ['accounts' => $accounts, 'status' => 'declined'];
$types = ['accounts' => Connection::PARAM_INT_ARRAY, 'status' => \PDO::PARAM_STR];

答案 1 :(得分:1)

如果你想坚持订单无关紧要的public class MainActivity extends AppCompatActivity { private DrawMapView mapView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); MapboxAccountManager.start(this, getString(R.string.access_token)); setContentView(R.layout.activity_main); mapView = (DrawMapView) findViewById(R.id.mapView); mapView.onCreate(savedInstanceState); mapView.getMapAsync(new OnMapReadyCallback() { @Override public void onMapReady(MapboxMap mapboxMap) { mapView.setBorderPoints(Arrays.asList(new LatLng(-36.930129, 174.958843), new LatLng(-36.877860, 174.978108), new LatLng(-36.846373, 174.901841), new LatLng(-36.829215, 174.814659), new LatLng(-36.791326, 174.779337), new LatLng(-36.767680, 174.823242))); } }); } @Override public void onResume() { super.onResume(); mapView.onResume(); } @Override public void onPause() { super.onPause(); mapView.onPause(); } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); mapView.onSaveInstanceState(outState); } @Override public void onLowMemory() { super.onLowMemory(); mapView.onLowMemory(); } @Override protected void onDestroy() { super.onDestroy(); mapView.onDestroy(); } } 语法,你必须做一些额外的工作,但我会向你展示一种更简单的方法来绑定参数:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:mapbox="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="ua.com.omelchenko.mapboxlines.MainActivity">

    <ua.com.omelchenko.mapboxlines.DrawMapView
        android:id="@+id/mapView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        mapbox:center_latitude="-36.841362"
        mapbox:center_longitude="174.851110"
        mapbox:style_url="@string/style_mapbox_streets"
        mapbox:zoom="10"/>
</RelativeLayout>

在这种情况下,我们最终得到: :param

// store all your parameters in one array
$params = array(
    ':status' => 'declined'
);

// then, using your arbitrary array of id's ...
$array_of_ids = array(5, 6, 12, 14);

// ... we're going to build an array of corresponding parameter names
$id_params = array();
foreach ($array_of_ids as $i => $id) {
    // generate a unique name for this parameter
    $name = ":id_$i"; // ":id_0", ":id_1", etc.

    // set the value
    $params[$name] = $id;

    // and keep track of the name
    $id_params[] = $name;
}

// next prepare the parameter names for placement in the query string
$id_params = implode(',', $id_params); // ":id_0,:id_1,..."
$sql = "select * from user where id in ($id_params) and status = :status";

这种方法也适用于字符串数组。

答案 2 :(得分:-1)

您需要将它们包装在数组中

$stmt->bindValue(':userId', array($accounts), array(\Doctrine\DBAL\Connection::PARAM_INT_ARRAY));

http://doctrine-dbal.readthedocs.io/en/latest/reference/data-retrieval-and-manipulation.html#list-of-parameters-conversion

修改

我应该详细说明一下。你不能像这样绑定一个数组,不要直接准备sql execute作为文档中的例子。

$stmt = $conn->executeQuery('SELECT * FROM articles WHERE id IN (?)',
array(array(1, 2, 3, 4, 5, 6)),
array(\Doctrine\DBAL\Connection::PARAM_INT_ARRAY));
  

您无法将值数组绑定到单个预准备语句参数