Solucionando advertencias inesperadas en el código de opciones del tema

4 ago 2019, 11:21:20
Vistas: 53
Votos: 0

Actualmente he construido mi propia clase para registrar opciones del tema, y funciona bien, pero cuando empecé a hacer algunos ajustes comenzaron a aparecer advertencias y no puedo identificar qué he hecho mal.

Explicaré el código antiguo y nuevo para ayudarte a entender el problema.

Funcionando correctamente

El siguiente constructor acepta tres arrays que representan elementos de menú, ajustes (secciones/campos) y widgets.

public function __construct($menu = array(), $sections = array(), $widgets = array())

Dentro del constructor comencé a establecer propiedades y llamar a los hooks necesarios para la página de ajustes, que debería registrar los ajustes y campos usando las correspondientes funciones callback. Cada campo debe renderizarse dinámicamente según su nombre de clase, algo como $render = new $field_class($field, $value, $this); (Cada campo tiene su propia clase que extiende la clase de ajustes del tema. Lo mostraré más adelante).

El método de renderizado de campo

 /**
  * Función callback para campos de sección de clase
  */
    public function field_input($field){
        if(isset($field['callback']) && function_exists($field['callback'])){
        }
        if(isset($field['type'])){
            $field_class = 'ANONY_optf__'.ucfirst($field['type']);
            if(class_exists($field_class)){
                $fieldID = $field['id'];
                $fieldDefault = isset($field['default']) ? $field['default'] : '';
                $value = (isset($this->options->$fieldID))? $this->options->$fieldID : $fieldDefault;                   
                $render = new $field_class($field, $value, $this);
                $render->render();
            }
        }
    }

Cada clase de campo acepta tres argumentos: $field que contiene los datos del campo (ej. id, etiqueta, tipo), $value de la opción correspondiente al id del campo y un objeto de la clase padre $this.

Luego en la clase específica del campo, el siguiente código. (El problema está dentro del constructor, así que solo mostraré eso)

class ANONY_optf__Switch extends ANONY__Theme_Settings{ 

function __construct( $field = array(), $value ='', $parent = NULL ){
    if( is_object($parent) ) parent::__construct($parent->sections, $parent->args);
    $this->field = $field;
    $this->value = $value;  
}
}

Como puedes ver, el campo switch extiende la clase de ajustes del tema.

No funciona

Hasta aquí todo bien, pero una vez que empecé a mover algunas líneas de la clase padre (Método de renderizado de campo) al constructor específico del campo, comenzaron a aparecer advertencias.

Así que la función de renderizado quedó así:

public function field_input($field){

        if(isset($field['callback']) && function_exists($field['callback'])){

        }
        //Array de inputs que tienen mismo marcado HTML
        $mixed_types = ['text','number','email', 'password','url'];

        if(isset($field['type'])){
            $field_class = 'ANONY_optf__'.ucfirst($field['type']);

            //Nombre de clase estática para inputs que tienen mismo marcado HTML
            if(in_array($field['type'], $mixed_types)) $field_class = 'ANONY_optf__Mixed';
            
            if(class_exists($field_class)){
                                    
                $field = new $field_class($field, $this);
                
                $field->render();
            }
        }
    }

Y el constructor específico del campo:

function __construct( $field = array(), $parent = NULL ){
    if( is_object($parent) ) parent::__construct($parent->sections, $parent->args, $parent->widgets);

    $this->field = $field;

    $fieldID = $this->field['id'];
                
    $fieldDefault = isset($this->field['default']) ? $this->field['default'] : '';

    $this->value = (isset($parent->options->$fieldID))? $parent->options->$fieldID : $fieldDefault;
}

Después de esto recibo:

Warning: Illegal string offset 'id'.

Notice: Uninitialized string offset: 0.

aunque solo he movido el código del padre al hijo.

No sé si he podido explicar lo que ha pasado para que entiendas el problema. Pero espero que puedas ayudar, y por supuesto estoy dispuesto a explicar más si es necesario. Gracias de antemano.

Nota

Las advertencias aparecen pero todo se renderiza correctamente. Lo que podría significar que algo se llama dos veces pero la primera vez no pudo encontrar los valores.

Makiomar
Makiomar
151
Comentarios

No estoy seguro si esto ayuda, pero a tu constructor hijo le falta el parámetro $value - function __construct( $field = array(), $parent = NULL ) - debería ser function __construct( $field = array(), $value ='', $parent = NULL ) ? ¿Y probaste var_dump( $field ); para ver si contiene las claves/valores correctos?

Sally CJ Sally CJ
5 ago 2019 10:20:04

Gracias, pero no, el objeto se instancia sin el parámetro value new $field_class($field, $this)

Makiomar Makiomar
5 ago 2019 10:23:39

Pero puedo ver $render = new $field_class($field, $value, $this); en el código y también en el texto de tu pregunta... ¿Y cuál es el resultado del var_dump()?

Sally CJ Sally CJ
5 ago 2019 10:29:05

Creo que te estás perdiendo algo... si revisas los fragmentos en el código que no funciona, verás que todo está correcto... estás mirando los fragmentos que sí funcionan

Makiomar Makiomar
5 ago 2019 10:33:38

Ok, tal vez lo estoy... pero ¿qué tal si simplemente intentas agregar ese parámetro $value e instanciar la clase con tres parámetros? Y todavía no has respondido mi pregunta sobre lo del var_dump. Pruébalo e inspecciona la salida.

Sally CJ Sally CJ
5 ago 2019 10:43:34