Skip to content

Commit 009580d

Browse files
fixed the Php::include_once() call for PHP 8.1
1 parent 1d878ff commit 009580d

File tree

6 files changed

+146
-15
lines changed

6 files changed

+146
-15
lines changed
+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
; configuration for phpcpp module
2+
; priority=30
3+
extension=includeonce.so
4+

Examples/IncludeOnce/Makefile

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
CPP = g++
2+
RM = rm -f
3+
CPP_FLAGS = -Wall -c -I. -O2 -std=c++11
4+
PHP_CONFIG = $(shell which php-config)
5+
LIBRARY_DIR = $(shell ${PHP_CONFIG} --extension-dir)
6+
PHP_CONFIG_DIR = $(shell ${PHP_CONFIG} --ini-dir)
7+
8+
LD = g++
9+
LD_FLAGS = -Wall -shared -O2
10+
RESULT = includeonce.so
11+
12+
PHPINIFILE = 30-includeonce.ini
13+
14+
SOURCES = $(wildcard *.cpp)
15+
OBJECTS = $(SOURCES:%.cpp=%.o)
16+
17+
all: ${OBJECTS} ${RESULT}
18+
19+
${RESULT}: ${OBJECTS}
20+
${LD} ${LD_FLAGS} -o $@ ${OBJECTS} -lphpcpp
21+
22+
clean:
23+
${RM} *.obj *~* ${OBJECTS} ${RESULT}
24+
25+
${OBJECTS}:
26+
${CPP} ${CPP_FLAGS} -fpic -o $@ ${@:%.o=%.cpp}
27+
28+
install:
29+
cp -f ${RESULT} ${LIBRARY_DIR}/
30+
cp -f ${PHPINIFILE} ${PHP_CONFIG_DIR}/
31+
32+
uninstall:
33+
rm ${LIBRARY_DIR}/${RESULT}
34+
rm ${PHP_CONFIG_DIR}/${PHPINIFILE}

Examples/IncludeOnce/class.php

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
/**
3+
* Class.php
4+
*
5+
* Empty class, we just try to double-include this file to run into a
6+
* "class already defined" error
7+
*
8+
* @author Emiel Bruijntjes <[email protected]>
9+
* @copyright 2024 Copernica BV
10+
*/
11+
12+
/**
13+
* Include ourselves (should do nothing)
14+
*/
15+
include_once(__FILE__);
16+
my_include_once(__FILE__);
17+
18+
/**
19+
* Class definition
20+
*/
21+
class SillyClass {}

Examples/IncludeOnce/includeonce.cpp

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/**
2+
* callphpfunction.cpp
3+
* @author Jasper van Eck<[email protected]>
4+
*
5+
* An example file to show the working of a php function call in C++.
6+
*/
7+
8+
/**
9+
* Libraries used.
10+
*/
11+
#include <iostream>
12+
#include <phpcpp.h>
13+
14+
/**
15+
* Namespace to use
16+
*/
17+
using namespace std;
18+
19+
/**
20+
* Function to test the Php::include_once() call
21+
* @param &params
22+
*/
23+
void my_include_once(Php::Parameters &params)
24+
{
25+
// the string
26+
Php::Value path = params[0];
27+
28+
// do the call
29+
Php::include_once(path.stringValue());
30+
}
31+
32+
33+
// Symbols are exported according to the "C" language
34+
extern "C"
35+
{
36+
// export the "get_module" function that will be called by the Zend engine
37+
PHPCPP_EXPORT void *get_module()
38+
{
39+
// create extension
40+
static Php::Extension extension("include_once","1.0");
41+
42+
// add function to extension
43+
extension.add<my_include_once>("my_include_once", {
44+
Php::ByVal("path", Php::Type::String),
45+
});
46+
47+
// return the extension module
48+
return extension.module();
49+
}
50+
}

Examples/IncludeOnce/includeonce.php

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
/**
3+
* include_once.php
4+
*
5+
* An example file to show the working of a php function call in C++.
6+
*/
7+
8+
/**
9+
* Include the file (should include the file only once)
10+
*/
11+
my_include_once(__DIR__."/class.php");
12+
my_include_once(__DIR__."/class.php");
13+
my_include_once(__DIR__."/class.php");
14+
15+
/**
16+
* Construct object
17+
*/
18+
$x = new SillyClass();

zend/file.cpp

+19-15
Original file line numberDiff line numberDiff line change
@@ -62,33 +62,37 @@ bool File::compile()
6262
if (_opcodes) return _opcodes->valid();
6363

6464
// we are going to open the file
65-
zend_file_handle fileHandle;
65+
zend_file_handle filehandle;
6666

6767
#if PHP_VERSION_ID < 80100
68+
6869
// open the file
6970
if (zend_stream_open(ZSTR_VAL(_path), &fileHandle) == FAILURE) return false;
71+
7072
#else
71-
/**
72-
* zend_stream_open now only accepts the fileHandle object
73-
* Filename must now be set through the object path.
74-
*/
75-
fileHandle.filename = _path;
7673

77-
// open the file
78-
if (zend_stream_open(&fileHandle) == FAILURE) return false;
74+
// since php 8 (or 8.1? - this has not been checked), zend_stream_open just takes the file-handle, and we must associate it first with a filename
75+
zend_stream_init_filename_ex(&filehandle, _path);
76+
77+
// the stream if supposed to be open by now
78+
if (zend_stream_open(&filehandle) == FAILURE) return false;
79+
7980
#endif
8081

81-
// make sure the path name is stored in the handle (@todo: is this necessary? do we need the copy?)
82-
if (!fileHandle.opened_path) fileHandle.opened_path = zend_string_copy(_path);
82+
// make sure the path name is stored in the handle (@todo: is this necessary? do we need the copy,
83+
// this was copied from zend_execute.c, maybe deals with case when opened_path is not set for
84+
// special types of files that are correctly opened, but that do not expose path-info, while this info
85+
// is still needed by the subsequent zend_compile_file() call for error messages?)
86+
if (!filehandle.opened_path) filehandle.opened_path = zend_string_copy(_path);
8387

8488
// we need temporary compiler options
8589
CompilerOptions options(ZEND_COMPILE_DEFAULT);
8690

8791
// create the opcodes
88-
_opcodes.reset(new Opcodes(zend_compile_file(&fileHandle, ZEND_INCLUDE)));
92+
_opcodes.reset(new Opcodes(zend_compile_file(&filehandle, ZEND_INCLUDE)));
8993

9094
// close the file handle
91-
zend_destroy_file_handle(&fileHandle);
95+
zend_destroy_file_handle(&filehandle);
9296

9397
// done
9498
return _opcodes->valid();
@@ -133,9 +137,6 @@ Value File::execute()
133137
// try compiling the file
134138
if (!compile()) return nullptr;
135139

136-
// add the entry to the list of included files
137-
zend_hash_add_empty_element(&EG(included_files), _path);
138-
139140
// execute the opcodes
140141
return _opcodes->execute();
141142
}
@@ -152,6 +153,9 @@ Value File::once()
152153
// check if this file was already included
153154
if (zend_hash_exists(&EG(included_files), _path)) return nullptr;
154155

156+
// add the entry to the list of included files
157+
zend_hash_add_empty_element(&EG(included_files), _path);
158+
155159
// execute the file
156160
return execute();
157161
}

0 commit comments

Comments
 (0)