This is a Python module for running PHP programs. It lets you import PHP functions, classes, objects, constants and variables to work just like regular Python versions.
# Examples
You can call functions:
```
>>> from phpbridge import php
>>> php.array_reverse(['foo', 'bar', 'baz'])
Array.list(['baz', 'bar', 'foo'])
>>> php.echo("foo\n")
foo
>>> php.getimagesize("http://php.net/images/logos/new-php-logo.png")
Array([('0', 200), ('1', 106), ('2', 3), ('3', 'width="200" height="106"'), ('bits', 8), ('mime', 'image/png')])
```
You can create and use objects:
```
>>> php.DateTime
<PHP class 'DateTime'>
>>> date = php.DateTime()
>>> print(date)
<DateTime PHP object (date='2018-05-03 22:59:15.114277', timezone_type=3, timezone='Europe/Berlin')>
>>> date.getOffset()
7200
>>> php.ArrayAccess
<PHP interface 'ArrayAccess'>
>>> issubclass(php.ArrayObject, php.ArrayAccess)
True
```
You can use keyword arguments, even though PHP doesn't support them:
```
>>> date.setDate(year=1900, day=20, month=10)
<DateTime PHP object (date='1900-10-20 22:59:15.114277', timezone_type=3, timezone='Europe/Berlin')>
```
You can loop over iterators and traversables:
```
>>> for path, file in php.RecursiveIteratorIterator(php.RecursiveDirectoryIterator('.git/logs')):
... print("{}: {}".format(path, file.getSize()))
...
.git/logs/.: 16
.git/logs/..: 144
.git/logs/HEAD: 2461
[...]
```
You can get help:
```
>>> help(php.echo)
Help on function echo:
echo(arg1, *rest)
Output one or more strings.
@param mixed $arg1
@param mixed ...$rest
@return void
```
You can import namespaces as modules:
```
>>> from phpbridge.php.blyxxyz.PythonServer import NonFunctionProxy
>>> help(NonFunctionProxy)
Help on class blyxxyz\PythonServer\NonFunctionProxy in module phpbridge.php.blyxxyz.PythonServer:
class blyxxyz\PythonServer\NonFunctionProxy(phpbridge.objects.PHPObject)
| Provide function-like language constructs as static methods.
|
| `isset` and `empty` are not provided because it's impossible for a real
| function to check whether its argument is defined.
|
| Method resolution order:
| blyxxyz\PythonServer\NonFunctionProxy
| phpbridge.objects.PHPObject
| builtins.object
|
| Class methods defined here:
|
| array(val) -> dict from phpbridge.objects.PHPClass
| Cast a value to an array.
|
| @param mixed $val
|
| @return array
[...]
```
You can index, and get lengths:
```
>>> arr = php.ArrayObject(['foo', 'bar', 'baz'])
>>> arr[10] = 'foobar'
>>> len(arr)
4
```
You can work with PHP's exceptions:
```
>>> try:
... php.get_resource_type(3)
... except php.TypeError as e:
... print(e.getMessage())
...
get_resource_type() expects parameter 1 to be resource, integer given
```
# Features
* Using PHP functions
* Keyword arguments are supported and translated based on the signature
* Docblocks are also converted, so `help` is informative
* Using PHP classes like Python classes
* Methods and constants are defined right away based on the PHP class
* Docblocks are treated like docstrings, so `help` works and is informative
* The original inheritance structure is copied
* Default properties become Python properties with documentation
* Other properties are accessed on the fly as a fallback for attribute access
* Creating and using objects
* Importing namespaces as modules
* Getting and setting constants
* Getting and setting global variables
* Translating exceptions so they can be treated as both Python exceptions and PHP objects
* Tab completion in the interpreter
* Python-like reprs for PHP objects, with information like var_dump in a more compact form
# Caveats
* On Windows, stdin and stderr are used to communicate, so PHP can't read input and if it writes to stderr the connection is lost
* You can only pass basic Python objects into PHP
* Namespaces can shadow names in an unintuitive way
* Because PHP only has one kind of array, its arrays are translated to a special kind of ordered dictionary
# Name conflicts
Some PHP packages use the same name both for a class and a namespace. As an example, take `nikic/PHP-Parser`.
`PhpParser\Node` is a class, but `PhpParser\Node\Param` is also a class. This means `phpbridge.php.PhpParser.Node` becomes ambiguous - it could either refer to the `Node` class, or the namespace of the `Param` class.
In case of such a conflict, the class is preferred over the namespace. To get `Param`, a `from` import has to be used:
```
>>> php.require('vendor/autoload.php')
<Composer.Autoload.ClassLoader PHP object (prefixLengthsPsr4=[...: (4)], ...>
>>> import phpbridge.php.PhpParser.Node as Node # Not the namespace!
>>> Node
<PHP interface 'PhpParser\Node'>
>>> from phpbridge.php.PhpParser.Node import Param # The class we want
>>> Param
<PHP class 'PhpParser\Node\Param'>
>>> import phpbridge.php.PhpParser.Node.Param as Param # Doesn't work
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: type object 'PhpParser\Node' has no attribute 'Param'
```
If there are no conflicts, things work as expected:
```
>>> from phpbridge.php.blyxxyz.PythonServer import Commands
>>> Commands
<PHP class 'blyxxyz\PythonServer\Commands'>
>>> import phpbridge.php.blyxxyz.PythonServer as PythonServer
>>> PythonServer
<PHP namespace 'blyxxyz\PythonServer'>
>>> PythonServer.Commands
<PHP class 'blyxxyz\PythonServer\Commands'>
```
# Installing
The only dependencies are PHP 7.0+, Python 3.5+, ext-json and ext-reflection. Composer can be used to install development tools and set up autoloading, but it's not required.
# Examples
You can call functions:
```
>>> from phpbridge import php
>>> php.array_reverse(['foo', 'bar', 'baz'])
Array.list(['baz', 'bar', 'foo'])
>>> php.echo("foo\n")
foo
>>> php.getimagesize("http://php.net/images/logos/new-php-logo.png")
Array([('0', 200), ('1', 106), ('2', 3), ('3', 'width="200" height="106"'), ('bits', 8), ('mime', 'image/png')])
```
You can create and use objects:
```
>>> php.DateTime
<PHP class 'DateTime'>
>>> date = php.DateTime()
>>> print(date)
<DateTime PHP object (date='2018-05-03 22:59:15.114277', timezone_type=3, timezone='Europe/Berlin')>
>>> date.getOffset()
7200
>>> php.ArrayAccess
<PHP interface 'ArrayAccess'>
>>> issubclass(php.ArrayObject, php.ArrayAccess)
True
```
You can use keyword arguments, even though PHP doesn't support them:
```
>>> date.setDate(year=1900, day=20, month=10)
<DateTime PHP object (date='1900-10-20 22:59:15.114277', timezone_type=3, timezone='Europe/Berlin')>
```
You can loop over iterators and traversables:
```
>>> for path, file in php.RecursiveIteratorIterator(php.RecursiveDirectoryIterator('.git/logs')):
... print("{}: {}".format(path, file.getSize()))
...
.git/logs/.: 16
.git/logs/..: 144
.git/logs/HEAD: 2461
[...]
```
You can get help:
```
>>> help(php.echo)
Help on function echo:
echo(arg1, *rest)
Output one or more strings.
@param mixed $arg1
@param mixed ...$rest
@return void
```
You can import namespaces as modules:
```
>>> from phpbridge.php.blyxxyz.PythonServer import NonFunctionProxy
>>> help(NonFunctionProxy)
Help on class blyxxyz\PythonServer\NonFunctionProxy in module phpbridge.php.blyxxyz.PythonServer:
class blyxxyz\PythonServer\NonFunctionProxy(phpbridge.objects.PHPObject)
| Provide function-like language constructs as static methods.
|
| `isset` and `empty` are not provided because it's impossible for a real
| function to check whether its argument is defined.
|
| Method resolution order:
| blyxxyz\PythonServer\NonFunctionProxy
| phpbridge.objects.PHPObject
| builtins.object
|
| Class methods defined here:
|
| array(val) -> dict from phpbridge.objects.PHPClass
| Cast a value to an array.
|
| @param mixed $val
|
| @return array
[...]
```
You can index, and get lengths:
```
>>> arr = php.ArrayObject(['foo', 'bar', 'baz'])
>>> arr[10] = 'foobar'
>>> len(arr)
4
```
You can work with PHP's exceptions:
```
>>> try:
... php.get_resource_type(3)
... except php.TypeError as e:
... print(e.getMessage())
...
get_resource_type() expects parameter 1 to be resource, integer given
```
# Features
* Using PHP functions
* Keyword arguments are supported and translated based on the signature
* Docblocks are also converted, so `help` is informative
* Using PHP classes like Python classes
* Methods and constants are defined right away based on the PHP class
* Docblocks are treated like docstrings, so `help` works and is informative
* The original inheritance structure is copied
* Default properties become Python properties with documentation
* Other properties are accessed on the fly as a fallback for attribute access
* Creating and using objects
* Importing namespaces as modules
* Getting and setting constants
* Getting and setting global variables
* Translating exceptions so they can be treated as both Python exceptions and PHP objects
* Tab completion in the interpreter
* Python-like reprs for PHP objects, with information like var_dump in a more compact form
# Caveats
* On Windows, stdin and stderr are used to communicate, so PHP can't read input and if it writes to stderr the connection is lost
* You can only pass basic Python objects into PHP
* Namespaces can shadow names in an unintuitive way
* Because PHP only has one kind of array, its arrays are translated to a special kind of ordered dictionary
# Name conflicts
Some PHP packages use the same name both for a class and a namespace. As an example, take `nikic/PHP-Parser`.
`PhpParser\Node` is a class, but `PhpParser\Node\Param` is also a class. This means `phpbridge.php.PhpParser.Node` becomes ambiguous - it could either refer to the `Node` class, or the namespace of the `Param` class.
In case of such a conflict, the class is preferred over the namespace. To get `Param`, a `from` import has to be used:
```
>>> php.require('vendor/autoload.php')
<Composer.Autoload.ClassLoader PHP object (prefixLengthsPsr4=[...: (4)], ...>
>>> import phpbridge.php.PhpParser.Node as Node # Not the namespace!
>>> Node
<PHP interface 'PhpParser\Node'>
>>> from phpbridge.php.PhpParser.Node import Param # The class we want
>>> Param
<PHP class 'PhpParser\Node\Param'>
>>> import phpbridge.php.PhpParser.Node.Param as Param # Doesn't work
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: type object 'PhpParser\Node' has no attribute 'Param'
```
If there are no conflicts, things work as expected:
```
>>> from phpbridge.php.blyxxyz.PythonServer import Commands
>>> Commands
<PHP class 'blyxxyz\PythonServer\Commands'>
>>> import phpbridge.php.blyxxyz.PythonServer as PythonServer
>>> PythonServer
<PHP namespace 'blyxxyz\PythonServer'>
>>> PythonServer.Commands
<PHP class 'blyxxyz\PythonServer\Commands'>
```
# Installing
The only dependencies are PHP 7.0+, Python 3.5+, ext-json and ext-reflection. Composer can be used to install development tools and set up autoloading, but it's not required.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
phpbridge-0.0.3.tar.gz
(25.4 kB
view details)
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
phpbridge-0.0.3-py3-none-any.whl
(35.8 kB
view details)
File details
Details for the file phpbridge-0.0.3.tar.gz.
File metadata
- Download URL: phpbridge-0.0.3.tar.gz
- Upload date:
- Size: 25.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/1.12.1 pkginfo/1.4.1 requests/2.20.1 setuptools/40.6.2 requests-toolbelt/0.8.0 tqdm/4.28.1 CPython/3.6.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3970deddd690c79076990aa5388f210d004fcfda7c1d401e2a09ff98d0b1d5b6
|
|
| MD5 |
aa3c5717de2b172a1676184e1fd28176
|
|
| BLAKE2b-256 |
1dda1437d867296ac84a756511102b4a01474d324286fff090ceb38e1da79988
|
File details
Details for the file phpbridge-0.0.3-py3-none-any.whl.
File metadata
- Download URL: phpbridge-0.0.3-py3-none-any.whl
- Upload date:
- Size: 35.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/1.12.1 pkginfo/1.4.1 requests/2.20.1 setuptools/40.6.2 requests-toolbelt/0.8.0 tqdm/4.28.1 CPython/3.6.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
455550a6bbbfde20eadf2737ff3b7f725965ccd72e8fbd63ba0e1d8d5c63464c
|
|
| MD5 |
f7415f39daa4ccb77500308165f07dc6
|
|
| BLAKE2b-256 |
709ee83cd2746343fe848c21c7da3db551d4adeee142648022caeecde0f5985b
|