如何在PDO中加载sqlite扩展?

vfhzx4xs  于 7个月前  发布在  SQLite
关注(0)|答案(4)|浏览(79)

首先,我想告知有关情况,以避免误解。
通过sqlite扩展,我提到了类似FTS的Sqlite扩展,而不是PHP的sqlite扩展。
我一直在使用PDO Sqlite在我的应用程序,它不能改变。
正如我看到的here,Sqlite扩展可以加载为查询如下所示:

SELECT load_extension('xyz.so');
$db = new PDO ( 'sqlite:qwert.db' );
$db->query("SELECT load_extension('myextension.so');");
$db->query("SELECT myfunction(name) FROM table");
$rows = $db->fetchAll(PDO::FETCH_CLASS, 'stdClass');

字符串

  • 注意:mysfunction是myextension的方法 *

但是当我从PDO测试这个查询时,它返回“not authorized”消息。
仅出于测试目的,我尝试使用以下代码加载PHP's Sqlite3 extension扩展:

$db = new SQLite3('qwer.db');
$db->loadExtension('xyz.so');


它的工作
据我所知,PDO Sqlite没有像loadExtension这样的方法来加载扩展
你知道我该怎么办吗?

70gysomp

70gysomp1#

找不到编译器标志,我们已经在pdo_sqlite扩展中使用快速的脏黑客解决了它。从sqlite3 API中使用sqlite3_enable_load_extension()修补sqlite_driver. c。

--- php-5.3.7.old/ext/pdo_sqlite/sqlite_driver.c    2012-01-06 11:04:44.000000000 -0500
+++ sqlite_driver.c 2012-01-06 08:16:58.000000000 -0500
@@ -718,6 +718,8 @@
        goto cleanup;
    }
 
+   sqlite3_enable_load_extension(H->db, 1);
+
    if (PG(safe_mode) || (PG(open_basedir) && *PG(open_basedir))) {
        sqlite3_set_authorizer(H->db, authorizer, NULL);
    }

字符串

hl0ma9xz

hl0ma9xz2#

我已经为PHP7.4+实现了一个解决这个问题的库,它不涉及重新编译PDO驱动程序。(它使用FFI读取PHP的内部内存结构)直接调用SQLite C API。你可以在this blog post中找到更详细的背景信息。我还不推荐在生产环境中使用这种解决方案,但它可能是测试或开发工作流的可行解决方案。

jaql4c8m

jaql4c8m3#

除了上面提到的变通方法,现在没有办法。如果你想在将来的某个地方检查进度,有an issue on PHP bugtracker

zqry0prt

zqry0prt4#

正如@yagmur对这个问题的回答,有一个解决方案是编译pdo_sqlite扩展。对于那些不知道如何做这个的人来说,就像我几天前一样,这个过程非常简单(我将假设一个Linux环境,因为我没有在Windows中编译这些东西的经验):
1.创建PHP source repository的克隆
1.访问您要使用的PHP版本的分支,例如PHP-8.2(您可以使用git checkout -b PHP-8.2.9 origin/PHP-8.2.9访问分支)
1.在文件夹ext/pdo_sqlite中,按照@yagmur的指示,在调用sqlite_driver.c文件中的sqlite3_set_authorizer函数的部分上方添加sqlite3_enable_load_extension(H->db, 1);行(该函数可能只调用一次)
1.编译扩展(下面我将解释编译的步骤)
1.将新编译的扩展(生成的pdo_sqlite.so文件)复制到您首选的文件夹中
1.配置php.ini文件,使pdo_sqlite路径与新路径匹配
1.重新启动PHP服务器
1.测试加载一个扩展
要编译扩展,您只需要访问终端中的文件夹ext/pdo_sqlite并执行以下命令:

phpize
./configure
make

字符串
扩展可能会在ext/pdo_sqlite/modules文件夹。
要配置php.ini,您可以使用php --ini命令,找到路径并编辑配置。可能会在php.ini文件中有这一行:extension=pdo_sqlite,但也可以在特定的文件中配置pdo_sqlite。将值更改为您编译的扩展名的路径。
如果你想测试它是否正常工作,你可以尝试这样做,在这个例子中加载SpatiaLite扩展:

$pdo = new PDO('sqlite:db/test.sqlite3');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$query = "CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, area POLYGON)";
$pdo->exec($query);

$query = "SELECT load_extension('/usr/local/lib/mod_spatialite')";
try{
    $pdo->exec($query);

    $geom = "POLYGON((-3.692895967970722 40.589246298614356,-3.489648897658222 40.687204044606595,-3.357812960158222 40.50367643938022,-3.585779268751972 40.413815011684214,-3.692895967970722 40.589246298614356))";
    $query = "INSERT INTO test (area) VALUES (ST_geomFromText('$geom'))";
    $rs = $pdo->exec($query);

    $query = "SELECT ST_asText(area), ST_area(area) from test";
    $statement = $pdo->prepare($query);
    $statement->execute();
    echo "<pre>";
    echo print_r($statement->fetchAll(), true);
    echo "</pre>";
}catch(Throwable $e){
    var_dump($e);
}


但只需打印SpatiaLite版本与SELECT spatialite_version()是一个最快的测试了。
附言:老实说,我不知道这是否对每个版本的sqlite_pdo都有效,或者PHP分支的版本对pdo_sqlite扩展的影响,如果你可以使用更高或更低版本的扩展,它将正常工作。

相关问题