Search by

Clases que generan HTML

Package info

bitbucket.org/piecesphp/html

pkg:composer/piecesphp/html

Statistics

Installs: 861

Dependents: 0

Suggesters: 0

v4.0.0 2026-10-26 17:10 UTC

This package is auto-updated.

Last update: 2026-10-26 17:16:38 UTC


README

Genera HTML desde PHP con objetos: elementos con atributos e hijos, campos de formulario, tablas, y un formateador que indenta el resultado.

Es parte del framework PiecesPHP, pero no depende de él.

Seguridad: escapa por defecto

El texto de un elemento y el valor de cada atributo se escapan al pintarlos (htmlspecialchars con ENT_QUOTES | ENT_SUBSTITUTE y UTF-8). Un valor que venga del usuario se puede pasar tal cual:

$p = new HtmlElement('p', $valorDelUsuario, null, ['title' => $valorDelUsuario]);
  • No lo escapes tú antes: saldría escapado dos veces (&). Las versiones anteriores a la 4.0.0 no escapaban y este README pedía escapar antes; ya no.
  • & sale como & y ' como '. Es HTML válido y el navegador lo muestra igual.
  • Los hijos no se escapan otra vez: ya se pintan escapados por su cuenta.
  • Si el HTML es tuyo y de confianza (nunca de un usuario), mételo con setRawContent(), o como hijos. Ver «HTML de confianza».
  • El nombre de la etiqueta y el de cada atributo no se escapan: se validan. Un nombre raro lanza una excepción (ver «Nombres válidos»).

Requisitos

Instalación

composer require piecesphp/html

Qué trae

Todo bajo PiecesPHP\Core\HTML:

ClaseQué es
HtmlElementUn elemento cualquiera: etiqueta, texto, hijos y atributos
AttributeUn atributo con uno o varios valores
Form, Input, Select, ButtonFormularios y sus campos
TableUna tabla a partir de nombres de columna y filas
FormatHtmlIndenta y embellece una cadena HTML
Collections\AttributeArray, ElementArray, FormElementArray, HtmlElementArrayColecciones tipadas
Interfaces\Element, Interfaces\FormElementLos contratos
Exceptions\MalformedAttributeException, MalformedChildException, MalformedTagExceptionAtributo, hijo o etiqueta inválidos

Uso

Un elemento con atributos e hijos

use PiecesPHP\Core\HTML\HtmlElement;

$enlace = new HtmlElement('a', 'Ver más', null, ['href' => '/articulos', 'class' => 'btn primario']);
$enlace->getAttributeInstance('class')->appendValue('grande');

$caja = HtmlElement::create('div', '', [$enlace]);

echo $caja; // o: $html = $caja->render(false);
  • render() sin argumento hace echo además de devolver la cadena. Para solo obtenerla: render(false) o (string) $elemento.
  • La salida pasa siempre por FormatHtml::format(), que la indenta.

HTML de confianza

El texto se escapa, así que <b> sale literal. Para HTML que escribes tú, setRawContent():

$p = (new HtmlElement('p', 'a & b '))->setRawContent('<b>negrita</b>');
echo $p->render(false);
// <p>a &amp; b
//     <b>negrita</b>
// </p>
// (render() pasa por FormatHtml, que indenta y parte en líneas)
  • El contenido crudo sale sin tocar, después del texto y antes de los hijos. Es el orden de innerHTML().
  • Otra forma de meter HTML sin escapar es construirlo con hijos (appendChild()): cada hijo se pinta bien por sí mismo.
  • getRawContent() lo devuelve. getText() devuelve el texto tal como lo diste, sin escapar.
  • HtmlElement::escape($cadena) expone el mismo escape, por si lo necesitas fuera de un elemento.
  • setRawContent() es de HtmlElement, no de la interfaz Element.
  • Nunca pases a setRawContent() un valor que venga del usuario: ahí no se escapa nada.

Un elemento sin cierre

$salto = new HtmlElement('br', '', null, null, false); // <br>

Atributos

$caja->setAttribute('data-id', '15');
$enlace->getAttribute('class');          // "btn primario grande", como cadena
$enlace->getAttribute('class', false);   // ['btn', 'primario', 'grande'], como lista
$caja->getAttribute('class');            // null: la caja no tiene clase
$caja->removeAttribute('data-id');

Un valor escalar se parte por el separador (un espacio por defecto): 'btn primario' son dos valores.

getAttribute() y Attribute::getValue() devuelven el valor crudo; el escape ocurre solo al pintar (Attribute::__toString()).

Nombres válidos

  • Etiqueta: una letra seguida de letras, dígitos o guiones (^[A-Za-z][A-Za-z0-9-]*$). Si no, el constructor de HtmlElement lanza MalformedTagException.
  • Atributo: no vacío y sin espacios, comillas, >, /, = ni caracteres de control. Si no, new Attribute(...) (y por tanto setAttribute()) lanza MalformedAttributeException.
new HtmlElement('div onclick=x'); // MalformedTagException
$caja->setAttribute('x" onclick="y', '1'); // MalformedAttributeException

Tablas

use PiecesPHP\Core\DataStructures\StringArray;
use PiecesPHP\Core\HTML\Table;

$tabla = new Table(new StringArray(['Nombre', 'Acción']));
$tabla->addRow(['Ana & Luis', $enlace]); // texto escapado; un Element entra como hijo de la celda
$tabla->printTable(false);

Una celda que es un Element entra como hijo del td; cualquier otra se convierte a cadena y se escapa.

Formularios

use PiecesPHP\Core\HTML\Form;

$form = new Form('POST', '/guardar');
$form->appendFieldSemantic(Form::text('nombre', null, 'Tu nombre'), 'Nombre', true);
$form->appendFieldSemantic(Form::email('correo'), 'Correo');
echo $form->render(false);

Fábricas estáticas de Form: label(), submit(), text(), hidden(), email(), password() y select().

Formatear HTML existente

use PiecesPHP\Core\HTML\FormatHtml;

echo FormatHtml::format('<div><p>Hola</p></div>');

Referencia de HtmlElement

MétodoQué hace
__construct(string $tag, string $text = '', $childs = null, $attributes = null, bool $doubleTag = true)$childs: un elemento, un array de elementos o una colección. $attributes: ['nombre' => valor], un Attribute o un AttributeArray
static create(...)Lo mismo, como fábrica
appendChild(Element $child)Añade un hijo. Devuelve $this
innerHTML(?Element $html = null)Sin argumento, el texto escapado, luego el contenido crudo y luego los hijos renderizados; con uno, sustituye los hijos
setRawContent(string $html) / getRawContent()HTML de confianza, sin escapar. setRawContent() devuelve $this
getText()El texto como se dio, sin escapar
static escape(string $value)El escape que usa el paquete
clearChilds()Quita los hijos
setAttribute(string $name, $value = null, ?string $separator = null)Devuelve $this
getAttribute(string $name, bool $outputAsString = true)Cadena, lista o null
getAttributeInstance(string $name) / removeAttribute(string $name) / getAttributes(bool $outputAsString = true)
render($echo = true): stringVer arriba
  • Un hijo de un tipo no admitido lanza MalformedChildException.
  • Una etiqueta inválida lanza MalformedTagException (ver «Nombres válidos»).
  • $attributes de un tipo no admitido en el constructor se ignora en silencio: 'x', 5, un objeto cualquiera o una lista sin claves (['a', 'b']) dan un elemento sin atributos, sin error.
  • setAttribute() con un valor que no es escalar, array ni null (por ejemplo, un objeto) lanza MalformedAttributeException. Dentro de un array, los valores no escalares se descartan en silencio.

Demo y pruebas

  • demo/index.php: un ejemplo mínimo con un enlace.
  • tests/FormatHtmlTest.php: 7 pruebas del formateador.
  • tests/HtmlElementEscapeTest.php: 17 pruebas del escape, el contenido crudo, la validación de nombres y las celdas de Table. Siguen sin pruebas el resto de HtmlElement, Attribute y los formularios (más allá del escape de Input, Select, Button y la etiqueta de Form).
composer install
php examples/readme.php            # ejecuta los ejemplos de este README; sale con 1 si alguno no da lo que dice
vendor/bin/phpunit

Cambios

Ver CHANGELOG.md.

Licencia

MIT. Ver LICENSE.