标签: php-internals

在这种简单的情况下,PHP拒绝接受返回类型的原因是什么?

在PHP 7.1.4中,使用严格类型,我有一个简单的面向对象的设置,涉及一些接口,以及一些实现这些接口的类.下面的例子,如你所料,工作正常.

declare(strict_types=1);

interface Loginable {
  public function login();
}

interface Upgradeable {
  public function upgrade(): Loginable;
}

class Person implements Upgradeable {
  function upgrade(): Loginable {
    return new PersonAccount();
  }
}

class PersonAccount implements Loginable {
  public function login() {
    ;
  }
}
Run Code Online (Sandbox Code Playgroud)

请注意Upgradable接口中的升级功能如何需要Loginable返回类型,这是另一个接口.在此示例中,Person类内的升级方法将Loginable接口指定为其返回类型,以匹配接口的规定.

但是,如果我现在尝试更准确地指定Person类的升级方法的返回类型,则会遇到致命错误.

class Person implements Upgradeable {
  function upgrade(): PersonAccount {
    return new PersonAccount();
  }
}
Run Code Online (Sandbox Code Playgroud)

请注意,我在这里要完成的是指定升级方法将返回一个对象,该对象根据类实现的接口实现所需返回类型的接口.这对我来说似乎非常合乎逻辑和正确,但PHP会说:

致命错误:Person :: upgrade()声明:PersonAccount必须与Upgradeable :: upgrade()兼容:可登录[...]

正如yivi已经在/sf/answers/3454715351/指出的那样,我想要实现的目标是不可能的.

如果涉及扩展类,我会接受PHP的抱怨,因为扩展类可以覆盖原始方法,这样就不能保证正确的返回类型.但是,在上述场景中,不扩展类.只有接口的实现,其目的是明确保证正确的实现.

请详细说明PHP拒绝接受上述声明返回类型的方法背后的原因!

php oop interface return-type php-internals

9
推荐指数
1
解决办法
109
查看次数

如何使用eclipse检查php函数源代码

我很好奇某些PHP函数是如何在内部实现的.例如array_values().

所以在eclipse中,我control click在函数名称上,它将我带到一个包含函数原型定义的页面,但不包含内部源代码.

在此输入图像描述

有没有办法看到使用eclipse的php函数的内部实现?(函数是用php还是c编写的)

如果不可能使用eclipse看到php源代码,那么有没有人有任何好的策略来搜索github上php源代码

php eclipse php-internals

9
推荐指数
1
解决办法
238
查看次数

PHP性能:复制与参考

嘿.今天我编写了一个小的基准脚本来比较复制变量的性能与创建对它们的引用.我期待,例如,创建对大型数组的引用将比复制整个数组慢得多.这是我的基准代码:

<?php
    $array = array();

    for($i=0; $i<100000; $i++) {
        $array[] = mt_rand();
    }

    function recursiveCopy($array, $count) {
        if($count === 1000)
            return;

        $foo = $array;
        recursiveCopy($array, $count+1);
    }

    function recursiveReference($array, $count) {
        if($count === 1000)
            return;

        $foo = &$array;
        recursiveReference($array, $count+1);
    }

    $time = microtime(1);
    recursiveCopy($array, 0);
    $copyTime = (microtime(1) - $time);
    echo "Took " . $copyTime . "s \n";


    $time = microtime(1);
    recursiveReference($array, 0);
    $referenceTime = (microtime(1) - $time);
    echo "Took " . $referenceTime . "s \n";

    echo "Reference / …
Run Code Online (Sandbox Code Playgroud)

php benchmarking reference php-internals

8
推荐指数
1
解决办法
3245
查看次数

如何使用Microsoft Visual C++ 2008编译PHP扩展?

我创建了一个PHP Hello World与Microsoft Visual C++ 2008扩展DLL我有权利php.ini(我知道,因为当我启用和禁用GD2扩展,有一个效果),但是当我加载扩展它没有履行附加模块弹出在phpinfo().

当我尝试测试函数(一个简单的double()函数)时,它显然不起作用.我用过这个教程).

如果有人可以提供他们在创建时创建的dll(看看如果我的搞砸了或者它是我的服务器)那么我很乐意测试它.

系统规格

操作系统:Windows(Vista)
服务器:WAMP
PHP:5.3.5(Xampp和IIS也已安装)

如果您想测试它是否适合您,请在此处下载.

当我运行命令时,php --ini我收到此错误:

PHP Startup: TalkPHP Extension: Unable to initalize module
Module compiled with build ID=API20090626, TS, VC9.
PHP   compiled with build IF=API20090626, TS, VC6.
These options need to match
Run Code Online (Sandbox Code Playgroud)

这是否意味着我必须使用版本9来编译PHP?

php c++ dll php-extension php-internals

8
推荐指数
1
解决办法
3886
查看次数

令人费解的php解析器错误

好吧也许不是那么令人费解,但在这里.

我正在乱搞并注意到这一点,只是<?php在一个文件中输入,只是那个,之后没有空格,只有标签,抛出一个解析错误.

只有一个空间,它工作正常.我想知道是否有人知道为什么解析器会窒息,因为除非省略结束标记,否则完全没问题.谢谢.

php parsing php-internals

8
推荐指数
1
解决办法
802
查看次数

为什么file_get_contents比memcache_get更快?

我正在使用file_get_contents从磁盘加载XML文件,作为测试,我发现我可以file_get_contents()在3.99秒内使用1,000次加载156K文件.我已经将用于加载的部分子类化并用memcache层替换它,并且在我的开发机器上找到我可以在4.54秒内完成1000个相同文档的加载.

我很欣赏file_get_contents()会做一些缓存,但看起来它实际上比一个众所周知的缓存技术更快.在单个服务器上,性能是否file_get_contents()可以达到?

我通过Macports,OS X 10.6.8使用PHP 5.2.17.

编辑:我发现这个大小的XML文档,使用MEMCACHE_COMPRESSED标志有一个小小的好处.通过内存缓存的1,500个负载在6.44秒内完成(压缩)而不是6.74(不带).然而两者都比慢file_get_contents,在5.71秒内负载相同.

php file-io memcached php-internals

8
推荐指数
1
解决办法
1820
查看次数

PHP扩展中的SEG错误

我编写了一个PHP扩展来访问静态库中的函数,我将PHP构建为CGI,一切似乎都有效(经过几天的工作......)

一旦所有工作都兴奋,我重新编译PHP而没有调试我在其中的消息.(php_printf("here111");.... php_printf("sending arguments...");)

然后,它就停止了工作.我在静态库中调用的函数有效,我通过直接从另一个可执行文件调用它来测试它.

我使用调试符号(--enable-debug)构建了PHP,并且可以在gdb中将其调试到一定程度.

我仍然在努力弄清楚出了什么问题.似乎lib(diffFst)中的函数似乎无法读取输入参数.

268     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssssssd",
269        &filA, &filA_len,
270        &nomvarA, &nomvarA_len,
271        &filB, &filB_len,
272        &nomvarB, &nomvarB_len,
273        &filO, &filO_len,
274        &newnomvar, &newnomvar_len,
275        &mult
276        ) == FAILURE) {
277         RETURN_LONG(-100);
278     }
279 
280     php_printf("Read arguments:\nfilA: %s, nomvara: %s\nfilB: %s, nomvarB: %s\nfilO: %s, nomvarO: %s\nMult: %0.3f\n",
281        filA,nomvarA, filB,nomvarB, filO,newnomvar, mult);
282 
285     ier = difffst_(filA,nomvarA, filB,nomvarB, filO,newnomvar, mult);
Run Code Online (Sandbox Code Playgroud)

当我调用此函数时,该php_printf()语句将起作用并打印出正确的值.但是,当我让它调用difffst_函数时,我在尝试读取输入变量时会遇到段错误.

diffFst函数是用fortran编写的:

  5 …
Run Code Online (Sandbox Code Playgroud)

php c segmentation-fault php-extension php-internals

8
推荐指数
1
解决办法
352
查看次数

如何从PHP扩展中返回数组,而不将其复制到内存中?

我正在开发一个PHP扩展,其中一个对象方法需要返回一个数组zval.

该方法如下:

ZEND_METHOD(myObject, myMethod)
{
    zval **myArrayProperty;
    if (zend_hash_find(Z_OBJPROP_P(getThis()), "myArrayProperty", sizeof("myArrayProperty"), (void **) &myArrayProperty) == FAILURE) {
        RETURN_FALSE;
    }
    RETURN_ZVAL(*myArrayProperty, 1, 0);
}
Run Code Online (Sandbox Code Playgroud)

代码工作正常,并做了预期的事情 - 它返回对象的myArrayProperty.但是,我想优化这个过程.

myArrayProperty存储一个可能很大的数组.并且RETURN_ZVAL()宏复制该数组以返回值.复制过程需要花费大量时间来获取内存并复制所有数组值.同时,返回的数组通常用于只读操作.所以一个很好的优化是使用PHP的机制与引用计数,不要重复myArrayProperty内容.相反我会提高refcountmyArrayProperty,只是返回指针.当使用PHP扩展中的变量时,这与通常使用的策略相同.

但是,似乎没有办法 - 你必须复制值才能从PHP扩展函数返回它.更改函数签名以通过引用返回值不是一个选项,因为它链接属性和返回值 - 即稍后更改返回值,也会更改属性.这不是一种可接受的行为.

无法参与引用计数看起来很奇怪,因为PHP中的代码相同:

function myMethod() {
{
    return $this->myArrayProperty;
}
Run Code Online (Sandbox Code Playgroud)

通过引用计数机制进行优化.这就是我在StackOverflow上提出这个问题的原因,以防我错过了什么.

那么,有没有办法从PHP扩展中的函数返回一个数组,而不是在内存中复制数组?

php c php-extension php-internals

8
推荐指数
2
解决办法
1961
查看次数

PHP生成器 - 垃圾收集

简单的问题.

何时或如何,由PHP或你自己做生成器破坏他们的堆栈?

请看以下示例:

function doWork(): Generator
{
    // create some objects.
    $o1 = new stdClass();
    $o2 = new stdClass();

    // pause here and wait for data.
    $value = yield 1;

    // By referencing the above objects, they shouldn't destruct.
    $o1->property = $value;
    $o2->property = $value;

    yield $o1;
    yield $o2;

    // End of stack.
}

// Create the generator.
$generator = doWork();

$value = $generator->current(); // $value will equal 1.

if ($x) {
    $generator->send('Hello, World!'); // Continue execution of the generator. …
Run Code Online (Sandbox Code Playgroud)

php memory garbage-collection generator php-internals

8
推荐指数
1
解决办法
526
查看次数

PHP的MySQL Cursor实现以及它们如何管理内存

PHP中不同的MySQL游标如何管理内存?我的意思是,当我创建一个MySQL查询来检索一个大的结果集,然后获取MySQL资源时,查询检索的数据有多少存储在本地内存中,以及如何检索更多结果?光标是否自动获取所有结果,并在我使用fetch_array或是缓冲系统迭代资源时将它们提供给我?

最后,mysql中不同驱动程序的游标是否实现不同?有几个MySQL的驱动PHP可用mysql,mysqli,pdo等他们是否都遵循同样的做法?

php mysql php-internals

7
推荐指数
1
解决办法
4533
查看次数