Изменение файла класса PHP или заглушки программно - PullRequest
0 голосов
/ 11 мая 2018

Учитывая PSR-2-совместимый файл класса PHP (или заглушку)

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Car extends Model
{
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        //
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        //
    ];
}

Существует ли какой-либо инструмент для его простого анализа и изменения?В лучшем из миров с беглым API, может быть что-то вроде:

PhpClass::make(".../Car.php")
    ->setNamespace("Some/New/Namespace")
    ->use("Some\Dependency")
    ->addMethod($newFunctionBody)

Я знаю, что это может быть наивный пример, но насколько близок такой инструмент?Под инструментом я подразумеваю что-то, что я могу использовать в качестве зависимости, предпочтительно через композитор.

Сейчас у меня есть несколько работающее решение с использованием заполнителей и регулярных выражений, но оно начинает выходить из-под контроля во многих крайних случаях.Поэтому я думаю, что мне может понадобиться интерпретировать PHP.Спасибо за любой совет!

Ответы [ 2 ]

0 голосов
/ 04 июня 2018

Componere

Componere - это расширение PHP 7, доступное на pecl и задокументированное в руководстве по PHP ...

Приведенный ниже код регистрирует определение в таблице записей класса:

<?php
/* just making the example standalone */
class Model {}

class Car extends Model {
    public function something() {}      
}

trait SaysVroomVroomWhenPoked {

    public function poke() {
        return "Vroom Vroom";
    }
}

$def = new \Componere\Definition(Some\Place\Car::class, Car::class);

$def->addTrait(SaysVroomVroomWhenPoked::class);

$def->addMethod("newMethod", new \Componere\Method(function(){
    return 42;
}));

$def->register();

$car = new \Some\Place\Car();

printf("%s and %d\n", $car->poke(), $car->newMethod());
?>

Регистрация класса в таблице записей может быть желательна в некоторых случаях, поскольку ее действие распространяется на весь период действия запроса.

Приведенный ниже код исправляет конкретный экземпляр объекта с необходимыми функциями:

<?php
/* just making the example standalone */
class Model {}

class Car extends Model {
    public function something() {}      
}

trait SaysVroomVroomWhenPoked {

    public function poke() {
        return "Vroom Vroom";
    }
}

function accept(Car $car) {
    $patch = new \Componere\Patch($car);
    $patch->addTrait(SaysVroomVroomWhenPoked::class);

    $patch->addMethod("newMethod", new \Componere\Method(function(){
        return 42;
    }));
    $patch->apply();

    printf("%s and %d\n", $car->poke(), $car->newMethod());
}

$car = new Car();

accept($car);

var_dump(method_exists($car, "newMethod")); # false
?>

Обратите внимание, что выполнение этого везде гораздо менее эффективно, чем изменение определения, но его побочные эффекты исчезают, когда возвращается функция accept.

http://php.net/componere

Примечание: он имеет интерфейс жидкости, но для ясности я не использовал его здесь ...

Edit:

Я только что заметил ваш комментарий, выражающий интерес к предварительной обработке кода или, возможно, к использованию анонимных классов, а не манипуляций во время выполнения. Использование анонимных классов - отличная идея, но я не думаю, что вам нужен пример этого ...

Полное раскрытие: я написал Componere, и я написал реализацию анонимных классов для PHP ...

Все, что я скажу, чтобы отговорить вас от предварительной обработки, вероятно, сейчас будет довольно пустым ...

0 голосов
/ 11 мая 2018

На самом деле может быть способ сделать это.Концепция, которую вы ищете, называется «исправление обезьян».Я действительно не рекомендовал бы открывать эту банку с червями, если это вообще возможно, это по сути своей хакерской.Но я думаю, что есть несколько пакетов PHP, которые предлагают это.Возможно, вы также захотите взглянуть на концепцию Php7 «анонимные классы».Возможно, в сочетании с использованием Reflection для анализа класса, который вы пытаетесь эффективно изменить, вы можете создать анонимный класс для его репликации, использовать Reflection для него, чтобы получить в нем необработанный код, записать его во временный файл и каким-то образом поменять его местами.для оригинала в списке имен автопогрузчика => filepath во время выполнения.

Я не могу обещать, что все это будет работать, и может обещать, что это будет головная боль.Но если вы хотите повозиться, есть пища для размышлений.Если у вас все получится, пожалуйста, опубликуйте это здесь, я бы не против.Удачи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...