从XSLT调用PHP非静态成员函数

时间:2016-06-02 08:23:50

标签: php xslt

在PHP中,您可以使用<xsl:copy-of select="php:function('myfunc', 'param1')/*" /> 来允许在XSLT代码中调用PHP函数,如下所示:

::

您还可以使用<xsl:copy-of select="php:function('myclass::myfunc', 'param1')/*" /> 表示法对对象调用静态成员函数:

php:function

但是我想调用属于启动XSLT转换的类的非静态函数。

如何在XSLT中使用function removeBookmarkFromUrl(url) { var arr = url.split("#"); return arr[0]; } $(document).ready(function () { $('input:radio[name=lang]').change(function() { var url = window.location.href; var selectedLang = $(this).attr('id'); url = removeBookmarkFromUrl(url); if (url.indexOf('?lang') >= 0 || url.indexOf('&lang') >= 0) { var pos = (url.indexOf('?lang') >=0 ) ? url.indexOf('?lang') : url.indexOf('&lang'); var currentLang = url.slice(pos + 6, pos + 8); if (url.charAt(pos) == '?') { url = url.replace('?lang=' + currentLang, '?lang=' + selectedLang); window.location = url; } else if (url.charAt(pos) == '&') { url = url.replace('&lang=' + currentLang, '&lang=' + selectedLang); window.location = url; } } else { if (url.indexOf('?') >= 0) { window.location = url + '&lang=' + selectedLang; } else { window.location = url + '?lang=' + selectedLang; } } }); }); 来调用PHP对象上的非静态成员函数?

(我指的是如何在XSLT中指定对象,以及我使用什么语法来表示我想调用该对象的成员函数。)

不依赖于全局变量的解决方案将是首选!

1 个答案:

答案 0 :(得分:0)

好吧,我想我已经完成了这个,但它有点狡猾。欢迎其他答案。

拿这个例子类:

class Example {
    protected $greet;
    public function __construct($g) {
        $this->greet = $g;
    }
    public function greeting($name) {
        return $this->greet . ' ' . $name;
    }
}

然后你需要这些辅助函数:

// Serialise the object and replace ASCII null characters with @NULL@
function xsltSerialize($object)
{
    return str_replace("\0", '@NULL@', serialize($object));
}

// Unserialise $object (of type $className) and call $func
function callMember($className, $object, $func, $param)
{
    $rf = new ReflectionMethod($className, $func);
    $o = unserialize(str_replace('@NULL@', "\0", $object));
    return $rf->invoke($o, $param);
}

然后你可以像这样使用它:

// This is the object that will get called from within the XSL.  Note
// that we are passing a parameter to the constructor which gets saved
// in the object instance, so we will know later whether we have the
// original object back again.
$e = new Example('Hello');

// Pass the object to the XSL code, after serialising it
$xsl->setParameter('', 'obj', xsltSerialize($e));

然后在XSLT中,调用PHP callMember()函数,提供类的原始名称,序列化对象,要调用的函数以及该函数的参数。

Output is
<xsl:value-of select="php:function('callMember', 'Example', $obj, 'greeting', 'everyone')"/>

最终结果是在对象的正确实例上调用成员函数:

Output is Hello everyone

单词“Hello”表示在XSLT外部的构造函数中设置的值已保留,“everyone”表示从XSLT传入的参数也是通过的。

这种方法存在许多缺点:

  1. 序列化然后反序列化非常浪费资源,如果执行次数太多或者在大型对象上会影响性能。
  2. 并非所有对象都可以序列化。
  3. 只能将固定数量的参数传递给函数,因此对于不同数量的参数,您需要不同版本的callMember()
  4. 由于序列化过程,XSLT调用将在对象的副本上运行,而不是原始副本。因此,一旦函数返回,您对该对象所做的任何更改都将丢失。 (在对同一对象的两次XSLT调用之间甚至不会保留状态。)