Git Product home page Git Product logo

ephp's Introduction

ePHP

Build Status Codecov License: LGPL 2.1 Hex

PHP Interpreter pure 100% Erlang. This interpreter was made for enhance and give flexibility to projects that requires an interface for plugins or addons without new compilations.

In the same way, you can use for server PHP pages in an easy way.

The port is not 100% complete, please refer to compatibility table.

IMPORTANT {: .warning}

The generation of the documentation is made using edown which isn't compatible with OTP 23 and OTP 24 at the moment. If you need to generate the documentation, install an OTP 22 and run make doc removing the _build directory if you compiled previously with a more recent OTP version.

Who's using it?

At the moment, this project has been tested using Kazoo and connected to FreeSwitch for writing small VoIP controlling apps.

In addition, it was tested using XMPP in the Snatch Project (deprecated).

You can find here an implementation for Phoenix Framework to use PHP instead of EEx for some pages.

And as embedded project, it's planned to be included in Conta.

If you are using ePHP and you are proud about you created, please let me know for extending the list.

Donation

If you want to support the project to advance faster with the development you can make a donation. Thanks!

paypal

Why PHP over Erlang?

When I was leading a team of developers in Spain, in Telco companies the most in use language was PHP. Even for handling concurrency, they were using some techniques with POSIX mutexes, shared memory and nohup background processes. That was a nightmare.

We discover Erlang these days (back in 2009) and started to use it to solve all of those issues and create a more reliable software. But the rest of the companies and even our clients continued using and requesting to make changes using PHP. This way I discover that we could gave them the flexibility of PHP as logic language to develop their code and the reliability of Erlang virtual machine (BEAM).

We tried, however, to use previously other solutions like SpiderMonkey or V8 to use JavaScript like other projects do (Riak and CouchDB), but we realize those solutions create the dependency of an external library which isn't working as a breeze most of the times. And the requirement was about to use PHP and not other different languages.

The motivation was: have a 100% Erlang code PHP interpreter. No C extensions and trying to minimize as much as possible the dependencies to have as little as possible the interpreter. That's because JSON, MySQL and other extensions are in different repositories letting you to include them in your code or not, depending on your needs.

In 2016, after fight again and again against the same issue (heredoc), I decided to rewrite the parser in 100% Erlang code. This let me to get rid of neotoma and speed up a bit the parsing of the code. Indeed, this let me to solve the heredoc issue and continue implementing the rest of the PHP syntax easily.

In 2019, ePHP was published finally as a hex package. In addition, I developed a new library for Elixir which shows how to use ephp for Elixir projects and add the ability to use PHP templates for Phoenix Framework projects: ephp_template.

You can see even an example of ephp in use for the running on-the-fly of PHP code to play the Leprechaun game (source code here).

And a post to know how to write a stand-alone server with Erlang, without write a single line of Erlang code and using PHP for the logic of a XMPP component here.

Requirements

ePHP requires to be run over an Erlang/OTP 19+, but not all the versions are full compatible or recommended. See the list:

Erlang Version Support Notes
27.0 βœ“ Recommended if you use OTP 27
26.2 𐄂 fails compiling parser
26.1 𐄂 fails compiling parserΒ 
26.0 βœ“ Recommended if you use OTP 26
25.3 βœ“ Recommended if you use OTP 25
25.2 βœ“
25.1 βœ“ Β 
25.0 βœ“
24.3 βœ“ Recommended if you use OTP 24
24.2 βœ“
24.1 βœ“ Β 
24.0 βœ“
23.3 βœ“ Recommended if you use OTP 23
23.2 βœ“
23.1 βœ“
23.0 βœ“
22.3 βœ“ Recommended if you use OTP 22
22.2 βœ“
22.1 βœ“
22.0 βœ“
21.3 Β βœ“ Recommended if you use OTP 21
21.2 βœ“
21.1 βœ“
21.0 βœ“
20.3 𐄂 fails in math lib
20.2 βœ“ Recommended if you use OTP 20
20.1 βœ“
20.0 βœ“
19.3 βœ“ Recommended if you use OTP 19
19.2 βœ“
19.1 βœ“
19.0 βœ“

Getting Started

A simple way to use, is include in your project rebar.config the following dependency line:

    {ephp, "0.2.7"}

And use the following code in your project:

{ok, Ctx} = ephp:context_new(),
PHP = "<? $a = 5 * 23; ?>Result for $a = <?=$a?>",
{ok, Text} = ephp:eval(Ctx, PHP).

The result stored in Text should be:

Result for $a = 115

Controversial License

Yes, looks like not so many people like GPL lincenses and they didn't realised that LGPL 1.2 is very light license in comparison. I mean, I'm the author and it's not my aim to sue to the people for using this software. LGPL is only requesting feedback in case you change and improve the library, that's all. In addition, if you are using it for a project and you have a credits section, it could be great to be included.

It's NOT required your project will be LGPL or even open source. I think it's the most important part.

Copyright (c) 2013-2024 Altenwald

Authors: "Manuel Rubio" ([email protected]).

ephp's People

Contributors

bitdeli-chef avatar kianmeng avatar manuel-rubio avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ephp's Issues

Support for `list(...) = ...`

The special use of list function should be implemented in the parser and in the VM to match each parameter in the list with a value returned.

Licensing question

I'd like to write an adaptor by means of which ephp could be used as a rendering library for Phoenix / Raxx / Cowboy / whatever - but I noticed the LGPL license - 99% of Erlang/Elixir everything is Apache 2 licensed. I'm not sure what the implications of LGPL/Apache is but it could be a stumbling block.

Stackoverflow has some rambling description - but I think I need a flowchart to grok it πŸ˜‚

https://opensource.stackexchange.com/questions/5664/linking-from-lgpl-2-1-software-to-apache-2-0-library

Anyhow, my question is, considering you're the committer with the exception of a single commit, are you fully committed to LGPL or would you consider Apache 2 licensing?

Variables storage

The original PHP stores the variables and adds a reference to them so, when an object, array or resource is assigned to a new variable, instead of a clone, it's copied a reference to the real data. In this way, the references are easier to handle internally and the weird behaviour for unset is understood better.

At this moment the implementation for unset is not compatible when we use it with objects because we're not destroying the object.

There are an ID for each instance

Watching var_dump output I realize the number assigned to the instance is an unique ID for each running:

object(stdClass)#1 (2) {
  ["name"]=>
  string(4) "John"
  ["surname"]=>
  string(5) "Smith"
}

The number #1 is regarding to the ID. If we create another instance whatever the class came from the number is increased.

Weird atanh implementation...

The return for atanh in Erlang is based on the math C library and depending on the OS it is different even giving results. Because of that:

php_atanh(_Context, _Line, {_, Number}) ->
    % math:atanh(Number); % FIXME: the implementation is not reliable
    1 / 2 * math:log((1 + Number) / (1 - Number)).

Any idea? Should we have to keep it as is?

Support for OTP 20

It drops the following message in the compilation:

===> Compiling ephp

=ERROR REPORT==== 7-Jul-2017::20:12:40 ===
Error in process <0.327.0> with exit value:
{function_clause,
    [{erl_parse,tokens,
         [{bin,0,
              [{bin_element,0,{integer,0,56},default,default},
               {bin_element,0,{integer,0,46},default,default},
               {bin_element,0,{integer,0,52},default,default},
               {bin_element,0,{integer,0,48},default,default},
               {bin_element,0,{integer,0,32},default,default},
               {bin_element,0,{integer,0,50},default,default},
               {bin_element,0,{integer,0,48},default,default},
               {bin_element,0,{integer,0,49},default,default},
               {bin_element,0,{integer,0,55},default,default},
               {bin_element,0,{integer,0,45},default,default},
               {bin_element,0,{integer,0,48},default,default},
               {bin_element,0,{integer,0,49},default,default},
               {bin_element,0,{integer,0,45},default,default},
               {bin_element,0,{integer,0,49},default,default},
               {bin_element,0,{integer,0,49},default,default}]},
          []],
         [{file,"erl_parse.yrl"},{line,1432}]},
     {epp,user_predef,2,[{file,"epp.erl"},{line,601}]},
     {epp,init_server,4,[{file,"epp.erl"},{line,541}]}]}
===> Compiling src/ephp_parser.erl failed
src/ephp_parser.erl:none: internal error in parse_module;
crash reason: function_clause

  in function  erl_parse:tokens/2
     called as erl_parse:tokens({bin,0,
      [{bin_element,0,{integer,0,56},default,default},
       {bin_element,0,{integer,0,46},default,default},
       {bin_element,0,{integer,0,52},default,default},
       {bin_element,0,{integer,0,48},default,default},
       {bin_element,0,{integer,0,32},default,default},
       {bin_element,0,{integer,0,50},default,default},
       {bin_element,0,{integer,0,48},default,default},
       {bin_element,0,{integer,0,49},default,default},
       {bin_element,0,{integer,0,55},default,default},
       {bin_element,0,{integer,0,45},default,default},
       {bin_element,0,{integer,0,48},default,default},
       {bin_element,0,{integer,0,49},default,default},
       {bin_element,0,{integer,0,45},default,default},
       {bin_element,0,{integer,0,49},default,default},
       {bin_element,0,{integer,0,49},default,default}]},
 [])
  in call from epp:user_predef/2 (epp.erl, line 601)
  in call from epp:init_server/4 (epp.erl, line 541)

make: *** [compile] Error 1

`print` and `echo` functions with `or` and `and`

The use of and and or with the echo and print functions is tricky:

print "OK" or die("trying");

It could be understood as (1):

print("OK") or die("trying");

or maybe as (2):

print("OK" or die(trying));

The trade-off of the original line above is the ambiguity. The current implementation for PHP is the (1). And thanks to a work-around in the parser it is working for simple structures, but it should be improved.

Complete SO information

In ephp_lib_info.erl there are specific parts needed of information, for example, in PHP the information about:

  • OS:

    • {unix, darwin} as Darwin
    • {unix, linux} as Linux
    • {win, nt} as WINNT
    • {win, _} as Windows
  • OS Family:

    • {unix, darwin} as Darwin
    • {unix, linux} as Linux
    • {win, nt} as WINNT
    • {win, _} as Windows
  • OS EOL: this part is forced to only \n.

It should be configured properly.

`Ephp.eval` always fails with `no case clause matching` error

Expected Behavior

out variable from out = EphpContext.get_output(ctx) contains hello worldthis is awesome

https://github.com/osbre/ephp_web/blob/main/lib/ephp_web/ephp_plug.ex#L34

Actual Behavior

getting an error πŸ‘€

** (CaseClauseError) no case clause matching: {:EXIT, {:function_clause, [{:ephp_interpr, :run, [#Reference<0.4106486204.4208197636.168118>, {:{}, [], [:print_text, "hello world\n", {{:line, 1}, {:column, 2}}]}, false], [file: ~c"/home/o/code/ephp_web/deps/ephp/src/ephp_interpr.erl", line: 77]}, {:lists, :foldl, 3, [file: ~c"lists.erl", line: 1350]}, {:ephp_interpr, :process, 3, [file: ~c"/home/o/code/ephp_web/deps/ephp/src/ephp_interpr.erl", line: 25]}, {:ephp, :eval, 3, [file: ~c"/home/o/code/ephp_web/deps/ephp/src/ephp.erl", line: 182]}, {EphpWeb.EphpPlug, :call, 2, [file: ~c"lib/ephp_web/ephp_plug.ex", line: 34]}, {Bandit.Pipeline, :call_plug, 2, [file: ~c"lib/bandit/pipeline.ex", line: 110]}, {Bandit.Pipeline, :run, 6, [file: ~c"lib/bandit/pipeline.ex", line: 25]}, {Bandit.HTTP1.Handler, :handle_data, 3, [file: ~c"lib/bandit/http1/handler.ex", line: 27]}]}}

message from the terminal window

Steps to Reproduce the Problem

Linked GitHub repository to easily reproduce the problem: https://github.com/osbre/ephp_web

  1. git clone [email protected]:osbre/ephp_web.git && cd ephp_web
  2. mix deps.get
  3. mix run --no-halt
  4. curl http://0.0.0.0:4000
  5. Check the output from command 3

Specifications

  • Version:
    • ephp: latest from the master branch, therefore commit d32fc68
      • same result with 0.3.1 from Hex.
    • Elixir 1.15.0 (compiled with Erlang/OTP 25)
    • Erlang/OTP 25 [erts-13.2.2.1] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit:ns]
  • Platform: Linux
  • Subsystem: Linux Mint 21 with 5.15.0-75-generic kernel

NaN and Infinity are a bit tricky

For PHP these numbers are identified by the PHP_INT_MIN usually, but Erlang hasn't a limit for integers so, I did the implementation as:

to_int(infinity) -> -9223372036854775808;
to_int(nan) -> -9223372036854775808;

Maybe it should be fixed in another way (see ephp_data.erl for further details).

Heredoc

At this moment, using PEG it's not possible to parse heredoc. Code as:

<?php

$data = <<<EOF
this is a free
text for be stored in \$data variable
EOF;

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.