session_start - Modificación de clase de tiempo de ejecución de PHP
session start php (3)
Así que quiero poder agregar / eliminar métodos de clase en tiempo de ejecución. Antes de que me digas que es una práctica horrible en un principio, podría ser, pero realmente no me importa. La razón por la que deseo poder hacer esto es porque quiero que la aplicación sea muy modular, por lo que algunos complementos podrían ampliar alguna clase base y agregar métodos sin matar a la aplicación principal.
Por ejemplo, supongamos que tengo la siguiente clase:
class User {
protected $Id;
protected $Name;
protected $Password;
protected $PostsPerPage;
}
Y digamos, algunos complementos agregan la posibilidad de que los usuarios cambien su configuración de visibilidad, agregando una propiedad $ Visible a la clase. La clase se convertiría en:
class User {
protected $Id;
protected $Name;
protected $Password;
protected $PostsPerPage;
protected $Visible;
}
Esto se puede lograr a través de __get y __set, pero la implementación más común es para obtener y establecer propiedades generadas en tiempo de ejecución, y sería una molestia codificar pseudo getters y setters para cada propiedad añadida, así como usar __set es un no- no en mi opinión.
La otra idea que tenía era almacenar la configuración del usuario por separado, en otra matriz como $ UserVisiblitySettings [userid], pero eso hace que las cosas no sean como OO como me gustaría que fueran.
La siguiente idea era hacer una clase de ayuda, algo como esto:
class UserHelper {
public function SetVisiblity($user_object,value);
}
Entonces, podría usar __get y __set para implementar métodos / clases de "amigos", pero eso suena demasiado hackish. Si tuviera que ir por ese camino también podría sobrecargar __call, __get y __set. Además, no estoy tan seguro de que esta sea una buena práctica de OOP, y se vería feo también.
La última idea que tuve fue tener alguna función para crear clases dinámicamente en tiempo de ejecución mediante el uso de eval () (este es el único uso válido de eval que también pude encontrar). Básicamente, obtenga la definición de la clase de un archivo, haga una búsqueda simple de corchetes para encontrar los corchetes de apertura y cierre de la clase y envíelos a eval.
Usar Runkit está fuera de lugar, ya que está desactualizado y prefiero no forzar al usuario a instalar alguna extensión.
Cuando busco mis ideas, la más simple y menos intensiva en la CPU parece ser la de sobrecargar _call y agregar una forma para que los métodos se registren en la clase.
Por favor, cualquier pensamiento que no sea "no hagas esto" es apreciado.
PHP no permite esto. Puede ser un lenguaje dinámico en otros aspectos, pero el sistema de clases es deliberadamente restrictivo. Puede instalar la extensión runkit , que cambia el idioma para permitir el burlarse de las clases en tiempo de ejecución (pero ya no está usando PHP normal), o puede usar los métodos mágicos para simularlo.
Puede anular la clase, pero no sé si puede volver a cargarla en la misma solicitud. se puede lograr algún cambio de comportamiento con un patrón de diseño de mediador (operador de eventos de Symfony), pero es necesario conocer los puntos de extensión por adelantado y disparar eventos / mensajes para que sean atrapados por una clase que se extienda en el futuro.
si puede esperar la próxima solicitud y borrar la caché si la tiene. Hice una herramienta que podría ayudarte. SourceEditor
Aquí también hay más respuestas a una pregunta similar, donde pongo ejemplos de código. ¿Cómo generar o modificar una clase de PHP en tiempo de ejecución?
La extensión RunKit puede hacerlo ( runkit_method_add()
, etc.)
Sin embargo, es una extensión experimental y ya estás apuntando a tu pie ...
Tienes otras opciones:
- Emular nuevos campos y métodos con
__get()
y__call()
- Utilice la
class Plugin extends BaseImplementation
subclases y el patrón de fábrica (elclass Plugin extends BaseImplementation
y tiene elPlugin
instantiate de fábrica en lugar deBaseImplementation
). Zend Plugin Loader hace algo como esto.
Es la solución con menos gastos generales, pero también se limita a un complemento que extiende una clase. - Agregue ganchos y use la delegación (Patrón de estrategia) (
$this->plugin->onFoo()
). Hay una biblioteca para esto .