Topic: Executing PHP code in Rails

For a project I'm working on I need to be able to execute a PHP include file from within my ruby code.  The way it should work is a user inputs some data into a form, that data is stored in a database but also passed to a PHP file in the form of GET variables.  The PHP file then works on the data and returns an output to ruby.  Ruby then has to accept that data and use it.  Any ideas on how this would work?

An example would be something like this:

1. User inputs data via a form.
2. The controller does two things.  Stores the data in a db and then passes that information on to a PHP file.
3. The PHP file receives the data and then works on it and outputs a result.
4. Ruby accepts the result back and works on it.

Re: Executing PHP code in Rails

If both the ruby and PHP scripts can share the same database, all you have to do is redirect to your PHP script when you're done storing the info in the DB, passing along some kind of record ID to the script so it knows what to process. Then once you're done at the PHP script, redirect back to the Ruby side.

Is there any particular reason you're not rewriting the PHP part in Ruby?

vinnie - rails forum admin

Re: Executing PHP code in Rails

The PHP script isn't something the users will see... it needs to run in the background and then return the value to ruby without leaving the page (ajax-style).

The PHP is an RSS aggregator that requires information from the user before retrieving the feed.  The feed is then stored in the db and returns to ruby whether it was successful or not.

So ideally we would have the user click submit, we display a loading icon, meanwhile we call the PHP script and then display the results to the user.

We plan on rewritting the PHP later on, but we don't have time or resources to do that right now.

Re: Executing PHP code in Rails

Have you considered using PHP CGI? Then you can run it through Ruby like this:

system('php /path/to/script')

Railscasts - Free Ruby on Rails Screencasts

Re: Executing PHP code in Rails

Could you elaborate on that?  Would I place that in the controller?  And how would I pass it variables and receive them back from the script?  I'm pretty new to Ruby on Rails and have never integrated with PHP before.  Thanks!

Re: Executing PHP code in Rails

Yeah, in the controller would be fine. It can go pretty much anywhere since it doesn't rely on anything Rails specific -- it is a global method.

In fact, backticks are probably better to use as this will return the result of the PHP script as a string. You can insert variables in it too like this:

result = `php /path/to/script "#{foo}" "#{bar}"`

Here it will print foo and bar variables as arguments to the script (converted to a string) so you can grab them in your PHP script. The output of the script will be returned and placed into the result variable in Ruby. Keep in mind the Ruby script will hang until the PHP script is done.

Railscasts - Free Ruby on Rails Screencasts

Re: Executing PHP code in Rails

That method should work awesome.  I'm going to implement it and try it out.  One more quick and should be obvious question.  What is the path to the 'public' folder?  Is that the root?  So: 'php /test.php "#{foo}" "#{bar}"'?

Re: Executing PHP code in Rails

The path to the rails project is stored in RAILS_ROOT, so you can do it like this:

`php #{RAILS_ROOT}/public/test.php "#{foo}"`

Railscasts - Free Ruby on Rails Screencasts

Re: Executing PHP code in Rails

Ok, I have a delay in there to simulate the file actually working on the data, and that seems to be working, but no data is displayed when I output the ruby variable on the next view.  Here is my code so far:

Controller:
# Some stuff goes here first that gets the variables below:
@result = 'php #{RAILS_ROOT}/public/test.php "name = #{name}" "source = #{source}"'
# Then there is a redirect here to the view

View:
<%= @result %>

PHP:
<?php
    $name = $_GET['name'];
    $source = $_GET['source'];
    sleep(10);
    echo "name = " . $name . "source = " . $source;
?>

The PHP works if I type it directly into the browser...

Where am I going wrong?

Re: Executing PHP code in Rails

PHP CGI is a method of accessing PHP via the command line.  The ruby code you're using (`php #{RAILS_ROOT}/public/test.php "#{foo}"`) simply executes a command-line statement and returns the standard output from it.  To test this you should avoid using a browsers and type this straight into the command line.
What happens when you type:

php ./public/test.php name=my_name source=my_source

in the command line when you're in your application's directory?

Re: Executing PHP code in Rails

The problem is there is a redirect after you set the @result variable. This redirect sends a completely new request so no variables are carried over (except the session data). How about not doing a redirect and simply rendering the view? If you rename the view file the same as the action name and remove the redirect, it should just render it.

Railscasts - Free Ruby on Rails Screencasts

Re: Executing PHP code in Rails

@danger: When I type that directly into the terminal I get "name = source = " without it displaying the variables.  That would be a problem.

@ryanb: The way I have this setup is that when you want to add an rss feed you click on the 'add' button which takes you to the 'add_feed' page as directed by the corresponding method (named 'add_feed') this page has a form that get submitted to the 'save_feed' method in the controller which if successful redirects it to the index page.  But we need to have the index page say whether it was able to retrieve the feed or not based on the output of the php file... is there a way to verify the contents of the php output and then display whether it was successful or not... or if it even received the correct/if any values from ruby?

I hope this all makes sense.

Re: Executing PHP code in Rails

cantinflas83 wrote:

When I type that directly into the terminal I get "name = source = " without it displaying the variables.  That would be a problem.

The variables aren't getting set because there's no HTTP request - it is through the command line so you need to use those arguments. I think $argv is an array of the arguments. Take a look at the manual for details.

cantinflas83 wrote:

But we need to have the index page say whether it was able to retrieve the feed or not based on the output of the php file... is there a way to verify the contents of the php output and then display whether it was successful or not... or if it even received the correct/if any values from ruby?

You would probably want to use flash:

result = `php ...`
unless result.blank? # probably more extensive testing here
  flash[:notice] = 'Feed added successfully'
  redirect_to :action => 'index'
end

Flash is stored inside the session, so it is accessible on the next request.

# index.rhtml or layout file
<%= flash[:notice] %>

Last edited by ryanb (2006-11-09 18:55:32)

Railscasts - Free Ruby on Rails Screencasts

Re: Executing PHP code in Rails

I didn't realize that the php command was a terminal command.  I think in this case were really going to need to use an HTTP command like GET instead of the terminal command.  Is there a way to do that?  I did some searching for GET in ruby and didn't come up with anything similar to what we need.  We basically need to send the php script some variables using GET and then receive them back using the same.  Is this even possible?  Or does it make sense?

Re: Executing PHP code in Rails

cantinflas83 wrote:

I didn't realize that the php command was a terminal command.  I think in this case were really going to need to use an HTTP command like GET instead of the terminal command.  Is there a way to do that?  I did some searching for GET in ruby and didn't come up with anything similar to what we need.  We basically need to send the php script some variables using GET and then receive them back using the same.  Is this even possible?  Or does it make sense?

I would look into screen scraping in Ruby. You can use the open method on any URL to call it, so you can call your PHP script using that:

require 'open-uri'

open('http://127.0.0.1/test.php?foo=bar') do |page|
  content = page.read
  # do something with content
end


You can get more information here.

Last edited by ryanb (2006-11-10 11:39:28)

Railscasts - Free Ruby on Rails Screencasts