瞎扯淡 从零开始 Ruby on PHP

dsh0416 · 发布于 2016年06月11日 · 最后由 zhanglintc 回复于 2016年08月16日 · 6641 次阅读
21472
本帖已被设为精华帖!

关于什叶派 PHP 教徒

PHP 早期的设计意图下整个语言都是模板驱动的。也就是说主要就是写个静态页面,在适当的需要动态的场合插入一些短小的 CGI 代码。然而逊尼派 PHP 教徒确认为 PHP 可以变成一门大而全的语言,摇身一变,强行又是 MVC 又是 MVC 的。各种框架层出不穷,抄完 Spring 又抄 Rails,甚至在一门模板驱动的语言中再搞一个模板渲染引擎。简直是异教。

Ruby on PHP

考虑到 Ruby 是一门强大的支持元编程的语言。很容易地我们能够将 Ruby 写成一门以模板来驱动的 CGI 语言。通过几行代码

require 'sinatra'

get '/' do
  redirect '/index.php'
end

get /^\/(.*?)\.php$/ do |c|
  erb c.to_sym
end

post /^\/(.*?)\.php$/ do |c|
  erb c.to_sym
end

这样,只需要在 ./view 下创建 erb 文件就可以当做 php 来写了,甚至连子目录都可以。 当然这样有一些小问题,比如,传进 erb 后连 request 来什么请求都不知道了。 所以我们可以稍作修改。

require 'sinatra'

get '/' do
  redirect '/index.php'
end

get /^\/(.*?)\.php$/ do |c|
  erb c.to_sym, locals: {request: request}
end

post /^\/(.*?)\.php$/ do |c|
  erb c.to_sym, locals: {request: request}
end

这样我们就有了一切 request 的数据了。自己在里面继续二次处理就是了。

模板渲染

erb 模板是有趣的,但是像 PHP 那样一次性插十几行代码就不是很方便了。其实 erb 里也有这样的方法,只是 deprecated 而已。

<body>
  <%
    puts 'foo'
    puts 'bar'
  %>
</body>

然而问题来了,erb 里并不支持 echo 那样的命令。这样我们没法在一坨 Ruby 代码中输出某个东西到网页。 但是,Rails 里的 ActionView 不是支持 concat 吗?那么我们稍稍用点元编程的技巧,支持一下 echo 咯。 所以我们得到了最终代码

# This is yet another PHP project
require 'sinatra'
require 'action_view'

lookup_context = ActionView::LookupContext.new('./views')
lookup_context.cache = false if development?
view_context = ActionView::Base.new(lookup_context)

module ActionView::Helpers::TextHelper
  def echo(string)
    output_buffer << string
  end
end

get '/' do
  redirect '/index.php'
end

get /^\/(.*?)\.php$/ do |c|
  view_context.render(file: c, locals: {request: request})
end

post /^\/(.*?)\.php$/ do |c|
  view_context.render(file: c, locals: {request: request})
end

我们也能在 erb 里愉快地 echo 了

<html>
  <body>
    Proudly Powered By 
    <br>
  <%
    echo 'PHP'
  %>
  </body>
</html>

副作用

根据上面的做法,我们把 Ruby 变成了一门什叶派 PHP 心目中 PHP 本该有的样子了。 顺便还带来了一点副作用那就是,Wappalyzer 把这个项目完全当做 PHP 项目了。 假如黑客试图用 PHP 的漏洞来攻击你,就等着看好戏吧。诶嘿~

共收到 16 条回复
15139

城会玩 :doge:

15295

:plus1:

296

👏

4楼 已删除
De6df3 huacnlee 将本帖设为了精华贴 06月12日 09:24
10594

哈哈,头部再输出一个 php-5.x 之类的就更像啦

68

从此Ruby on Java,Ruby on .Net都可以出世了。

9800

屌屌屌。

2369

https://github.com/migrs/rack-server-pages https://github.com/grosser/rhr

是兩款 rack application,讓你能只寫 .erb 不鳥 .rb,也就是把 ruby 當 php 用。

96

长见识.

136

很清真!

8885

可以,这很php!

377

@楼主 在erb中concat buffer 有2种做法:一种是用原生的模板语法<%= var %> ,类似php 5.4里的short tag <?=; 另一种就像你这样操作output buffer,但在sinatra里有比较简单/标准的做法:

# app.rb
helpers do
  def echo(str) @_out_buf << str.to_s end
end
# index.erb
<% echo 'hi' %>

anyway,楼主探索ActionView的技巧分享值得点赞

9800

从零开始的异世界生活。。。

96

既然已经用上php了,没必要再用ruby吧

21472

#13楼 @rainchen 很有道理,显然我没有好好读 sinatra 的源代码

96

加油。

24376

看几遍都觉得很欢乐

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册