简体   繁体   English

如何将php数组传递给postgres函数

[英]How to pass a php array to a postgres function

I'm trying with little success to pass a PHP array to the following function. 我正在努力将PHP数组传递给以下函数。

$recipients = array();
$recipients['6c2f7451-bac8-4cdd-87ce-45d55d152078'] = 5.00;
$recipients['8c2f3421-bac8-4cdd-87ce-45d55d152074'] = 10.00;

$originator = '5630cc6d-f994-43ff-abec-1ebb74d39a3f';
$params = array($originator, $recipients);

pg_query_params(_conn, 'SELECT widgetallocationrequest($1, $2)', $params);

$results = pg_fetch_all(pg_query_params);
...

The function accepts an array of a custom type: 该函数接受自定义类型的数组:

CREATE TYPE widgetallocationrequest AS (id uuid, amount numeric(13,4));

and enumeraties each item and performs an action: 并枚举每个项目并执行一项操作:

CREATE FUNCTION distributeWidgets(pid uuid, precipients widgetallocationrequest[])
 RETURNS BOOLEAN AS
 $BODY$
{
FOREACH v_recipient IN ARRAY precipients
LOOP
    ...do something
END LOOP;
}
  RETURN TRUE;
END;
$BODY$
LANGUAGE plpgsql VOLATILE STRICT
COST 100;

***(if the specific code sample contains errors it's only pseudocode, i'm really just looking for the best way to pass a php array to a postgres custom type array as a parameter so it can be enumerated in the postgres function)***

Update: I'm able to successfully call the function from postgres directly (not from PHP) with the following: 更新:我能够通过以下方式直接从postgres(而不是从PHP)成功调用该函数:

SELECT distributeWidgets('5630cc6d-f994-43ff-abec-1ebb74d39a3f',
ARRAY[('ac747f0e-93d4-43a9-bc5b-09df06593239', '5.00'), ('8c2f3421-bac8-4cdd-87ce-45d55d152074', '10.00')]::widgetallocationrequest[]);

But still not sure how to translate from this postgres example back into PHP 但仍然不确定如何从这个postgres示例转换回PHP

I've tried suggestions below and the output from the referenced functions yields the following error: 我已尝试过以下建议,引用函数的输出会产生以下错误:

在此输入图像描述

string from function is as follows: 函数的字符串如下:

'SELECT account.hldtoexpalloc('0d6311cc-0d74-4a32-8cf9-87835651e1ee', '0124a045-b2e8-4a9f-b8c4-43b1e4cf638d', '{{\"6c2f7451-bac8-4cdd-87ce-45d55d152078\",5.00},{\"8c2f3421-bac8-4cdd-87ce-45d55d152074\",10.00}}')'

UPDATE : I just noticed that you don't just need arrays, you need to use arrays of composite types. 更新 :我刚刚注意到你不仅需要数组,还需要使用复合类型的数组。 Ick. 伊克。 I've never needed to work with them, so I had to do a bit of checking. 我从来不需要和他们一起工作,所以我不得不做一些检查。

It seems that the correct PostgreSQL syntax for an array of widgetallocationrequest would be: 似乎widgetallocationrequest数组的正确PostgreSQL语法将是:

'{"(8c2f3421-bac8-4cdd-87ce-45d55d152074,10.0000)","(6c2f7451-bac8-4cdd-87ce-45d55d152078,5.0000)"}'::widgetallocationrequest[]

See how each composite-type row is enclosed in "(col1,col2)" within the array {a,b,c} container? 查看每个复合类型行如何包含在数组{a,b,c}容器中的"(col1,col2)"中?

Here's a PostgreSQL SQL example of how I created the value: 这是我创建值的PostgreSQL SQL示例:

-- Create the array of composites from a VALUES() statement
--
SELECT array_agg(x::widgetallocationrequest) 
FROM (VALUES 
    ('8c2f3421-bac8-4cdd-87ce-45d55d152074',10.00),
    ('6c2f7451-bac8-4cdd-87ce-45d55d152078',5.00)
) x;

... and how I verified it was valid: ......以及我如何验证它是有效的:

-- Unpack it back into a row-set of columns
SELECT * FROM unnest('{"(8c2f3421-bac8-4cdd-87ce-45d55d152074,10.0000)","(6c2f7451-bac8-4cdd-87ce-45d55d152078,5.0000)"}'::widgetallocationrequest[]);

Now, PHP's driver for Pg doesn't even support arrays, let alone arrays of composite types, so you're going to have to find someone else who wrote what you want or write it yourself. 现在,PHP的Pg驱动程序甚至不支持数组,更不用说复合类型的数组,所以你必须找到其他人写你想要的东西或自己编写。 Writing a reliable parser will be "fun" and not a productive use of time. 编写一个可靠的解析器将是“有趣的”,而不是有效利用时间。

Let's take another approach: produce a query that lets you call the function sanely by doing the conversion to a widgetallocationrequest[] inside PostgreSQL. 让我们采取另一种方法:生成一个查询,让你通过转换到PostgreSQL中的widgetallocationrequest[]widgetallocationrequest[]调用函数。

Here's a dummy function with the same arguments as your real one that we'll use as a call target: 这是一个虚函数,其参数与我们用作调用目标的真实函数相同:

CREATE OR REPLACE FUNCTION distributeWidgets(pid uuid, precipients widgetallocationrequest[]) RETURNS boolean AS $$
SELECT 't'::boolean;
$$ LANGUAGE 'sql';

You can see that it can be called with the array-of-composites syntax that's giving you so much trouble: 您可以看到它可以使用array-of-composites语法调用,这会给您带来很多麻烦:

SELECT distributewidgets(null, '{"(8c2f3421-bac8-4cdd-87ce-45d55d152074,10.0000)","(6c2f7451-bac8-4cdd-87ce-45d55d152078,5.0000)"}');

... but ideally you want to avoid producing anything that horrible from PHP, and the driver is missing important features so it can't do it for you. ...但理想情况下,您希望避免从PHP中产生任何可怕的东西,并且驱动程序缺少重要功能,因此无法为您执行此操作。

Instead, you can use a TEMPORARY table to produce the arguments, INSERT each argument row into the table with regular parameterized INSERT s, and then execute a query to execute the function. 相反,您可以使用TEMPORARY表生成参数,使用常规参数化INSERT将每个参数行INSERT到表中,然后执行查询以执行该函数。

BEGIN;

CREATE TEMPORARY TABLE dw_args ( id uuid, amount numeric(13,4) );

-- Use proper parameterized INSERTs from PHP, this is just an example
INSERT INTO dw_args(id,amount) VALUES ('8c2f3421-bac8-4cdd-87ce-45d55d152074',10.00);
INSERT INTO dw_args(id,amount) VALUES ('6c2f7451-bac8-4cdd-87ce-45d55d152078',5.00);

SELECT distributewidgets(null, array_agg(ROW(x.*)::widgetallocationrequest)) 
FROM dw_args x;

DROP TABLE dw_args;

COMMIT;

WARNING : The following is vulnerable to SQL injection if not handled very carefully. 警告 :如果处理不当 ,以下内容容易受到SQL注入攻击。 Use the above temp table approach if at all possible. 如果可能的话,使用上面的临时表方法。 Don't be bobby 's next victim; 不要成为鲍比的下一个受害者; read the PHP docs on SQL injection . 阅读有关SQL注入PHP文档

If for some reason it's absolutely necessary to run it all in one statement, you can instead produce a query with a VALUES set from PHP and convert that into a widgetallocationrequest[] using a PostgreSQL query. 如果由于某种原因,绝对有必要在一个语句中运行它,您可以使用从PHP设置的VALUES生成查询,并使用PostgreSQL查询将其转换为widgetallocationrequest[] I demonstrated it above, but here's how to combine it with a call to distributeWidgets(...) : 我在上面演示了它,但是这里是如何将它与对distributeWidgets(...)的调用结合起来:

SELECT distributewidgets(null, array_agg(x::widgetallocationrequest)) 
FROM (VALUES 
        ('8c2f3421-bac8-4cdd-87ce-45d55d152074',10.00),
        ('6c2f7451-bac8-4cdd-87ce-45d55d152078',5.00)
) x;

That's something you can build pretty easily in PHP using string manipulation, so long as you're really careful about SQL injection . 这是你可以使用字符串操作在PHP中轻松构建的东西,只要你对SQL注入非常小心。

Please use the temporary table approach if at all possible. 如果可能的话,请使用临时表方法。

See also PHP array to postgres array 另请参阅PHP数组到postgres数组

« Now, PHP's driver for Pg doesn't even support arrays, let alone arrays of composite types, so you're going to have to find someone else who wrote what you want or write it yourself. « 现在,PHP的Pg驱动程序甚至不支持数组,更不用说复合类型的数组了,所以你必须找到其他人写你想要的东西或自己编写。 Writing a reliable parser will be "fun" and not a productive use of time. 编写一个可靠的解析器将是“有趣的”,而不是有效利用时间。 » »

You can use Pomm's converter system It parses Arrays and HStores, you can even define your own types converters and it will handle arrays of it. 您可以使用Pomm的转换器系统它解析Arrays和HStore,您甚至可以定义自己的类型转换器,它将处理它的数组。

Hope that helps. 希望有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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