Maison  >  Article  >  développement back-end  >  Deliverer 1.0.8 prend déjà en charge PHP5 !

Deliverer 1.0.8 prend déjà en charge PHP5 !

藏色散人
藏色散人avant
2021-07-05 16:14:211286parcourir

Après deux semaines d'itération, Deliverer est actuellement mis à jour vers 1.0.8 https://github.com/zhoumengka...

Parce qu'il s'agit de résoudre le code ancestral J'ai également entendu des amis dire qu'il était toujours nécessaire de prendre en charge PHP5, j'ai donc travaillé dur pour résoudre ce problème de compatibilité de version pendant cette période. De façon inattendue, le problème est beaucoup plus difficile que prévu.

Après avoir enregistré les problèmes rencontrés lors du développement (principalement le travail physique) et avoir voulu les partager, Les amis intéressés peuvent forker une copie et devenir moins familiers avec le code fork一份之后,对代码不那么陌生,更期待各位个 PR

在 PHP7 中,函数或者方法在执行的时候都在zend_execute_data结构体中的execute_data->call->fbc中,而 PHP5 中对应的字段拿到的却是调用该函数的函数,二者差距比较大。

后来发现 PHP5 zend_execute_dataopline中查到了当前执行的函数信息,但在 PHP5.4 前后逻辑还有差异,需要区别对待(还好编译器提示报错的字段)

#if PHP_VERSION_ID < 50400
#define OP1_FUNCTION_PTR(n) (&(n)->op1.u.constant)
#else
#define OP1_FUNCTION_PTR(n) ((n)->op1.zv)
#endif

初次调用解决了,发现内嵌的调用,又不在opline里面了,而且版本不一样,取得地方也不一样,并且和上面的 opline 的判断版本号还不一样,这就只能靠体力来测了。

#if PHP_VERSION_ID < 50500
    if (execute_data->fbc != NULL)
    {
        fbc = execute_data->fbc;
    }
#else
    if (execute_data->call != NULL && execute_data->call->fbc != NULL)
    {
        fbc = execute_data->call->fbc;
    }
#endif

最终获取函数信息就是多层判断

    zend_function *fbc;

#if PHP_VERSION_ID < 70000
#if PHP_VERSION_ID < 50500
    if (execute_data->fbc != NULL)
    {
        fbc = execute_data->fbc;
    }
#else
    if (execute_data->call != NULL && execute_data->call->fbc != NULL)
    {
        fbc = execute_data->call->fbc;
    }
#endif
    if (fbc == NULL)
    {
        fbc = get_function_from_opline(execute_data->opline);
    }
#else
    if (execute_data->call != NULL && execute_data->call->func != NULL)
    {
        fbc = execute_data->call->fbc;
    }
#endif

在从 opline 里查询到的只是函数的名字,需要再去全局函数表里找到对应的函数指针

static zend_function *get_function_from_opline(zend_op *opline)
{
    zend_function *fbc;

    zval *function_name = OP1_FUNCTION_PTR(opline);

    if (Z_STRVAL_P(function_name) == NULL)
    {
        return NULL;
    }

    if (zend_hash_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name) + 1, (void **)&fbc) ==
        FAILURE)
    {
        return NULL;
    }

    return fbc;
}

整体来说 PHP5 的处理要比 PHP7 复杂很多,这也说明 PHP7 做的更好了,点赞。

这些就是这几天的开发工作,可能还有很多实际的线上环境没有遇到过,如果你有兴趣,可以使用这个工具来解决问题,也可以一起来完善这个小工具。

下周或者下下周我将加上 watch 功能,支持函数和方法的参数打印。主要是类比 Java 的 Arthas ,因为在其中 trace 和 watch 功能是我最常用的,虽然 PHP 可以线上直接修改加日志,但是这样毕竟不规范,走发布流程又太慢,我想这个 watch 功能还是很有必要的,大概是

$ ./bin/deliverer -w foo -n 3

表示监控foo函数3次调用后退出,并且打印出deliverer-request-id和其入参,可以再根据deliverer-request-id. .

En PHP7, les fonctions ou méthodes sont dans execute_data->call->fbc dans la structure zend_execute_data lorsqu'elles sont exécutées, tandis que celles correspondantes en PHP5 Ce que le champ obtient est la fonction qui appelle la fonction, et la différence entre les deux est relativement grande.

Plus tard, j'ai découvert que les informations sur la fonction actuellement exécutée ont été trouvées dans opline de PHP5 zend_execute_data, mais il existe des différences dans la logique avant et après PHP5.4 et doivent être traité différemment (heureusement le champ du compilateur qui a provoqué l'erreur)

rrreee

Le premier appel a été résolu, et il a été constaté que l'appel intégré n'était pas dans opline, et que la version était différente, et le L'endroit où il a été obtenu était différent, et il était cohérent avec le jugement de l'opline ci-dessus. Le numéro de version est toujours différent, nous ne pouvons donc nous fier qu'à la force physique pour le mesurer. rrreeeL'acquisition finale des informations sur la fonction est un jugement multicouche

rrreee
Ce qui est interrogé à partir de l'opline n'est que le nom de la fonction, et vous devez trouver le pointeur de fonction correspondant dans la table de fonctions globale🎜rrreee🎜En général , PHP5 est mieux traité que PHP7 C'est beaucoup plus compliqué, ce qui montre aussi que PHP7 fait mieux, bravo. 🎜🎜Voici les travaux de développement de ces derniers jours. Il se peut qu'il y ait de nombreux environnements en ligne réels que je n'ai pas rencontrés. Si vous êtes intéressé, vous pouvez utiliser cet outil pour résoudre le problème, ou vous pouvez travailler ensemble pour améliorer ce gadget. . 🎜🎜La semaine prochaine ou la semaine prochaine, j'ajouterai la fonction de montre pour prendre en charge l'impression des paramètres des fonctions et des méthodes. Principalement par analogie avec Arthas de Java, car les fonctions de trace et de surveillance sont ce que j'utilise le plus. Bien que PHP puisse modifier et ajouter directement des journaux en ligne, cela n'est finalement pas standardisé et le processus de publication est trop lent. toujours très C'est nécessaire, probablement 🎜rrreee🎜 signifie surveiller la fonction foo pour quitter après 3 appels, et imprimer le deliver-request-id et ses paramètres d'entrée, et puis en fonction de deliver-request-idAffichez la pile d'appels complète. 🎜🎜Si cela vous intéresse, veuillez lui donner une étoile, https://github.com/zhoumengkang/deliverer🎜🎜Si vous rencontrez des problèmes d'installation et d'utilisation, veuillez m'ajouter sur WeChat zhoumengkang pour venir harceler, mot de passe : Deliverer🎜🎜 Apprentissage recommandé : "🎜Tutoriel vidéo PHP🎜"🎜🎜

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer