我正在努力将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);
...
该函数接受自定义类型的数组:
CREATE TYPE widgetallocationrequest AS (id uuid, amount numeric(13,4));
并枚举每个项目并执行操作:
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)***
更新: 我能够通过以下方式直接(而不是从PHP)成功调用postgres中的函数:
SELECT distributeWidgets('5630cc6d-f994-43ff-abec-1ebb74d39a3f',
ARRAY[('ac747f0e-93d4-43a9-bc5b-09df06593239', '5.00'), ('8c2f3421-bac8-4cdd-87ce-45d55d152074', '10.00')]::widgetallocationrequest[]);
但仍然不确定如何将这个postgres示例转换回PHP
我已尝试过以下建议,引用函数的输出会产生以下错误:
函数中的
字符串如下:
'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}}')'
答案 0 :(得分:4)
UPDATE :我刚才注意到你不仅需要数组,还需要使用复合类型的数组。伊克。我从来不需要和他们一起工作,所以我不得不做一些检查。
似乎widgetallocationrequest
数组的正确PostgreSQL语法是:
'{"(8c2f3421-bac8-4cdd-87ce-45d55d152074,10.0000)","(6c2f7451-bac8-4cdd-87ce-45d55d152078,5.0000)"}'::widgetallocationrequest[]
查看每个复合类型行如何包含在数组"(col1,col2)"
容器中的{a,b,c}
中?
这是我如何创建值的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;
...以及我如何验证它是有效的:
-- 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[]);
现在,PHP的Pg驱动程序甚至不支持数组,更不用说复合类型的数组,所以你必须找到其他人写你想要的东西或自己编写。编写一个可靠的解析器将是“有趣的”,而不是有效利用时间。
让我们采取另一种方法:生成一个查询,让您通过转换到PostgreSQL中的widgetallocationrequest[]
来合理地调用函数。
这是一个虚拟函数,其参数与我们用作调用目标的真实参数相同:
CREATE OR REPLACE FUNCTION distributeWidgets(pid uuid, precipients widgetallocationrequest[]) RETURNS boolean AS $$
SELECT 't'::boolean;
$$ LANGUAGE 'sql';
你可以看到它可以用复合数组的语法调用,这会给你带来很多麻烦:
SELECT distributewidgets(null, '{"(8c2f3421-bac8-4cdd-87ce-45d55d152074,10.0000)","(6c2f7451-bac8-4cdd-87ce-45d55d152078,5.0000)"}');
...但理想情况下,您希望避免从PHP中产生任何可怕的东西,并且驱动程序缺少重要功能,因此无法为您执行此操作。
相反,您可以使用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;
警告:如果处理不当,以下内容容易受SQL injection攻击。如果可能的话,使用上面的临时表方法。不要成为bobby的下一个受害者;阅读PHP docs on SQL injection。
如果出于某种原因,绝对有必要在一个语句中运行它,您可以使用PHP中的VALUES
集生成查询,并使用PostgreSQL查询将其转换为widgetallocationrequest[]
。我在上面演示了它,但是这里是如何将它与对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;
只要您对SQL injection非常小心,就可以使用字符串操作轻松地在PHP中构建。
如果可能,请使用临时表方法。
答案 1 :(得分:3)
«现在,PHP的Pg驱动程序甚至不支持数组,更不用说复合类型的数组了,所以你必须找到其他人写你想要的东西或自己写的。编写一个可靠的解析器将是“有趣的”,而不是有效利用时间。»
您可以使用Pomm's converter system它解析Arrays和HStore,您甚至可以定义自己的类型转换器,它将处理它的数组。
希望有所帮助。