livy / cyrus
一个简单、面向对象的HTML模板/生成引擎。以古罗马建筑师的名字命名。
Requires
- zenodorus/strings: <2.0.0
Requires (Dev)
- phpunit/phpunit: 5.5.*
README
一个简单的基于对象的HTML生成器
用法
Cyrus使用对象和方法链来构建语义HTML元素,然后为您输出它们。
基本过程如下
$element = new Cyrus; $element->setEl('h1')->setClass('headline-el')->addContent('This is a Headline!')->display();
注意:您也可以使用Cyrus的内部工厂实例化Cyrus
$element = Cyrus::open(); // this is the same as `$element = new Cyrus;`
上面的代码将输出以下内容
<h1 class="headline-el">This is a Headline!</h1>
它支持任何标签类型,甚至您自己创建的
$fakeTag = new Cyrus; $fakeTag->setEl('fake-tag')->setContent('This isn\'t a real tag, but it\'s rendered anyway!')->display(); // <fake-tag> // This isn't a real tag, but it's rendered anyway! // </fake-tag>
通常,您链式调用方法时的顺序并不重要:$element->setClass('a-class')->setEl('p')与$element->setEl('p')->setClass('a-class')功能等价。然而,也有一些例外
- 嵌套(请参阅下一节)需要在子元素的开头使用
openChild和在结尾使用closeChild:任何其他顺序都会导致Cyrus失败。 - 覆盖内容的方法(例如
setEl)将覆盖链中先前调用的影响(除非由子隔板分隔)。 - 对
construct或display的调用应始终放在最后。由于它们不返回当前对象,它们会中断链,之后链式调用其他内容会导致一些错误。
初始类
在实例化Cyrus时,您可以通过以下方式指定主元素的类
$test = new Cyrus('test-1'); // or... $test = Cyrus::open('test-1'); // <div class="test-1"></div>
嵌套
您可以使用openChild和closeChild方法在元素内部嵌套其他元素
$nested = new Cyrus; $nested->setClass('parent') ->openChild()->setEl('span')->setClass('child')->addContent("I'm a child!")->closeChild() ->display(); // <div class="parent"> // <span class="child">I'm a child!</span> // </div>
对象嵌套
如果您将Cyrus对象传递给addContent,该对象将作为内容插入并自动展开。
$parent = new Cyrus; $child = new Cyrus; $child->setClass('child')->setEl('span')->addContent("I'm a child"); $parent->setClass('parent')->addContent($child)->display(); // <div class="parent"> // <span class="child">I'm a child!</span> // </div>
高级嵌套
您还可以通过使用nest方法并在调用openChild时分配ID来在链式调用终止后嵌套项目。这对于例如,如果您想在不需要创建整个Cyrus实例的情况下根据条件插入(或不是)内容,特别有用
$nestedAgain = new Cyrus; $nestedAgain->setClass('parent')->openChild('childID')->setClass('child')->closeChild(); if(true) : $nestedAgain->nest('childID')->addContent("I've been inserted!")->closeChild(); endif; $nestedAgain->display(); // <div class="parent"> // <div class="child">I've been inserted</div> // </div>
您必须直接指向嵌套元素,并且如果它们嵌套超过一个级别,必须定义整个路径。您可以通过使用/分隔id来实现,如下所示
$deepNesting = new Cyrus; $deepNesting->setClass('wrapper') ->openChild('level1')->setClass('level-1') ->openChild('level2')->setClass('level-2')->closeChild() ->closeChild(); $deepNesting->nest('level1/level2')->addContent('Content')->closeChild()->closeChild(); $deepNesting->display(); //<div class="wrapper"> // <div class="level-1"> // <div class="level-2">Content</div> // </div> //</div>
重要的是要注意,当打开这种嵌套上下文时,必须关闭所有子元素。有两个方便的方法可以帮助您做到这一点,即closeChildren和closeAll。closeChildren接受一个整数作为参数,并将关闭等于该整数数量的子元素。closeAll不接受任何参数,并将关闭当前上下文中所有打开的子元素。
方法
要了解方法如何操作,请查看源文件(./src)。每个方法都有良好的文档。
以下将涵盖一些特殊功能和边缘情况。
简写形式
任何以"set"开头的方法都可以使用简写形式调用,例如,您可以将setClass简写为class。
$element->el('blockquote'); // is equivalent to... $element->setEl('blockquote'); $element->attr('target', 'new'); // is equivalent to... $element->setAttr('target', 'new);
大多数嵌套函数也有简写形式
$el->o(); // is equivalent to... $el->openChild(); $el->c(); // is equivalent to... $el->closeChild(); $el->ca(); // is equivalent to... $el->closeAll(); $el->n('something'); // is equivalent to... $el->nest('something');
高级属性操作
取消设置属性
如果您发现需要取消设置一个属性,请使用false参数调用该属性的setAttr。
$element->setAttr('data-target', 'menu')->display(); // <div data-target="menu"></div> $element->setAttr('data-target', false)->display(); // <div></div>
无值属性
如果您想设置一个没有值的属性——例如 checked——您可以通过使用带 true 参数的 setAttr 来实现。
$element->setEl('input')->setAttr('type', 'radio')->setAttr('checked', true); // <input type="radio" checked>
setAttr 等等
setAttr 及其所有别名方法(例如 setClass、setURL 等)会将传递给同一属性的内容堆叠起来——它们不会覆盖任何内容。唯一的例外是,如果您将 false 作为参数传递给 setAttr,这将完全从元素中删除该属性。
这种值堆叠意味着以下语句是等价的
$element->setAttr('class', 'test1')->setClass('test2'); // is equivalent to... $element->setClass('test1 test2');
用假内容否定元素
使用 setContent 将元素的唯一内容显式设置为布尔值 false 将导致该元素不会生成。如果只想在元素有内容时显示元素,这可能很有用。为了使元素被否定,以下条件必须成立:
- 元素只有一个内容项(即 count($this->content) === 1)
- 该内容项正好等于布尔值
false(不是一个 假值,而是字面布尔值false) - 所讨论的元素不是自闭合元素
示例
$element->class('outside') ->content('hello') ->o()->class('inside')->content(false)->c(); // <div class="outside">hello</div>