stdlib_探索Webiny框架:StdLib组件

stdlib

There’s an adage about a developer’s career cycle:

关于开发人员职业生涯的一句格言:

  1. Doesn’t use frameworks

    不使用框架
  2. Discovers frameworks

    发现框架
  3. Writes his own framework

    写自己的框架
  4. Doesn’t use frameworks

    不使用框架

Point 4, of course, referring to the newfound ability to use Composer to build your own framework from various battle tested third party components.

第4点当然是指使用Composer从各种经过战斗测试的第三方组件构建自己的框架的新能力。

We all know there’s no shortage of frameworks in the PHP ecosystem, so it surprised me quite a bit to see another pop up rather recently.

我们都知道,PHP生态系统中并不缺少框架,因此最近才看到另一个弹出窗口让我感到非常惊讶。

alt

The framework is called Webiny, and, while packed to the brim with wheel reinventions they deem necessary, there are some genuinely interesting components in there that warrant taking a look. In this introductory post, we won’t be focusing on the framework as a whole, but on the most basic of its components – the StdLib.

该框架称为Webiny ,尽管他们认为必要的车轮重塑包装到了边缘,但其中确实包含一些真正有趣的组件,值得一看。 在这篇介绍性文章中,我们将不会专注于整个框架,而是最基本的组件StdLib。

Webiny StdLib (Webiny StdLib)

No, not that “std”. StdLib stands for Standard Library and is at the core of every other sub-component of the framework. It’s kind of like adding a dependency or two to a random PHP project and before you know what’s happening, Symfony/Yaml is somehow already in there.

不,不是那个“ std”。 StdLib代表标准库,并且是框架中每个其他子组件的核心。 这就像在一个随机PHP项目中添加一个或两个依赖项,在不知道发生了什么之前,Symfony / Yaml已经存在了。

Among other things, StdLib, like many others before it, makes dealing with scalars significantly simpler by adding a fluent object oriented interface on top and some helper methods. For example, there’s a lightweight URLObject which contains some helper methods for dealing with redirection, schemes, ports, etc. Besides helping out with OO wrappers, the library also offers some basic validation, methods that help with building other Webiny components, a simple singleton trait, and more.

与其他许多方法一样,StdLib通过在顶部添加一些流畅的面向对象的界面和一些辅助方法,使标量的处理变得更加简单。 例如,有一个轻量级的URLObject,其中包含一些用于处理重定向,方案,端口等的辅助方法。除了提供OO包装程序帮助之外,该库还提供了一些基本的验证方法,这些方法有助于构建其他Webiny组件,一个简单的单例特质等等。

Where StdLib differs significantly, is in the fact that it’s implemented as a set of Traits – a vastly underused part of modern PHP development. For example, the aforementioned URLObject is instantiated like so: $this->url('https://www.webiny.com/');, because the StdObject trait is added to any class that needs this functionality. Most of the other components of the Webiny framework are implemented as Traits as well due to their isolated nature – the team chose this approach in order to simplify the hierarchy structure of classes, aiming for as few extends as possible.

StdLib的显着不同之处在于,它是作为一组Traits来实现的 -这是现代PHP开发中未被充分利用的一部分。 例如,上述URLObject的实例化如下: $this->url('https://www.webiny.com/'); ,因为StdObject特性已添加到需要此功能的任何类中。 Webiny框架的大多数其他组件也由于其孤立的性质而也被实现为Traits -团队选择此方法是为了简化类的层次结构,目的是尽可能减少扩展。

StdLib is usable as a standalone package and can be cloned or “Composered” directly, or it can be pulled in as part of the entire framework. Let’s see what it offers, shall we?

StdLib可用作独立程序包 ,可以直接克隆或“组成” ,也可以作为整个框架的一部分引入。 让我们看看它能提供什么,对吗?

特征 (Features)

Internally, the StdLib consists of two sub-libs. One is the Exception set which is to be used only if you intend to build additional Webiny components (more on that in future tutorials). The other is the StdObject lib which contains the functionality we talked about before.

在内部,StdLib由两个子库组成。 一种是例外设置,仅当您打算构建其他Webiny组件时才使用(这将在以后的教程中详细介绍)。 另一个是StdObject库,其中包含我们之前讨论的功能。

Aside from that, the library contains traits that utilize these sub-libs.

除此之外,该库还包含利用这些子库的特征。

特质 (ComponentTrait)

The ComponentTrait is only useful if you’re building additional Webiny components – something we won’t be dealing with just yet. For now, we’ll skip it.

仅当您要构建其他Webiny组件时ComponentTrait才有用–我们暂时不会处理这些组件。 现在,我们将跳过它。

FactoryLoader特质 (FactoryLoaderTrait)

The FactoryLoaderTrait is useful in summoning class instances that have been dynamically defined. For example:

FactoryLoaderTrait在召唤已动态定义的类实例时很有用。 例如:

$className = 'myNameSpace\myClass';
$argument1 = 'Hello';
$argument2 = 'World';
$mustBe = 'myNameSpace\mySubClass';

To instantiate myClass with the arguments “Hello” and “World” while making sure the instance is of the mySubClass type, you can take the following two approaches:

要在确保实例属于mySubClass类型的同时使用参数“ Hello”和“ World”实例化myClass ,可以采用以下两种方法:

// standard PHP

try {
    $instance = new $className($argument1, $argument2);
    if (!($instance instanceof $mustBe)) {
        throw new Exception("Instances don't match!");
    }
} catch (Exception $e) {
    // Handle exception
}
// FactoryLoaderTrait approach

try {
    $instance = $this->factory($className, $mustBe, [$argument1, $argument2]);
} catch (Exception $e) {
    // Handle exception
}

As you can see, the second way is slightly shorter. Granted, the usefulness of this trait is questionable at best, especially considering that dynamic class names aren’t something one should use all that much, but when you take into account the level of standardization such a feature can bring across your entire organization/framework, the benefits become apparent. This trait’s approach is little more than a “coding standard” in dynamic class instantiation, but it can be a valuable one.

如您所见,第二种方法略短一些。 诚然,此特征的用途充其量是值得怀疑的,特别是考虑到动态类名不是一个人应该使用的太多的东西,但是当考虑到标准化程度时,此功能可以覆盖整个组织/框架,好处显而易见。 这种特性的方法仅是动态类实例化中的“编码标准”,但它可能是有价值的方法。

单例特质 (SingletonTrait)

The SingletonTrait instantly turns your class into a singleton. There are extensive discussions all around the web about the “bad” nature of singletons – not just ancient scriptures like these but even some of our own old posts discuss this – but on the off chance you need one and can’t have a decent DI container implementation to use instead, it’s here.

SingletonTrait立即将您的课程变成一个单例。 网上围绕单身人士的“坏”性质进行了广泛的讨论–不仅是像这样的古老经文 ,甚至我们自己的一些旧文章也对此进行了讨论 –但是,一次偶然的机会,您需要一个并且不能拥有像样的DI要使用的容器实现,它在这里。

One thing to keep in mind is the __construct conflicts. This particular trait doesn’t implement its own __construct method, meaning it can be used in both classes that have one of their own and those that don’t, unlike some other solutions, but it also means that you should adapt your class’ constructor to fit the singleton pattern if you choose to use this trait.

要记住的一件事是__construct冲突。 与某些其他解决方案不同,此特定特征没有实现自己的__construct方法,这意味着它可以在具有自己的类和不具有自身的类中使用,但这也意味着您应该调整类的构造函数如果选择使用此特征,则适合单例模式。

If you’re new to singletons, this post might help.

如果您是单身人士,那么此帖子可能会有所帮助

Another thing worth mentioning in this implementation is the fact that the trait implements a public init method and a protected _init method, executed in that order after the instance is created.

在此实现中值得一提的另一件事是,该特征实现了一个公共init方法和一个受保护的_init方法,该方法在创建实例之后按该顺序执行。

This is useful because you can use it as a post-creation initialization mechanism to further set up your singleton instance without having to rely on its constructor – maybe your class already has a defined constructor, and all you need is to turn it into a singleton, but the singleton mode of work needs some more tweaking? Perfect for init.

这很有用,因为您可以将其用作创建后的初始化机制,以进一步建立单例实例,而不必依赖其构造函数-也许您的类已经有一个已定义的构造函数,而您所需要做的就是将其转换为单例,但单例工作模式需要更多调整吗? 完美的init

性格特质 (StdLibTrait)

This trait is a combination of StdObjectTrait and ValidatorTrait. By itself, the StdLibTrait contains some json encode and decode helpers which are rather bare-bones right now, as well as a serialize and unserialize method which do essentially the same things as PHP’s counterparts. This may have been the place in which to instead use Symfony’s Serializer as a battle tested and multi-format supporting component.

此特征是StdObjectTrait和ValidatorTrait的组合。 StdLibTrait本身包含一些json编码和解码帮助程序,这些帮助程序目前还很简陋,还有一个序列化和反序列化方法,它们与PHP的对应方法本质上相同。 可能是在这里改为使用Symfony的序列化器作为经过战斗测试和多格式支持的组件。

验证者特质 (ValidatorTrait)

Starting with ValidatorTrait, it’s a simple collection of native PHP methods for checking type, but rewritten so they’re part of a class. I’m not sure of the reasoning behind this, as the API remains almost completely identical (self::isArray() vs is_array()), but I assume it has something to do with keeping the component extensible – being able to update these native methods without having to change the API lib-wide is guaranteed to be a priceless perk later on.

从ValidatorTrait开始,它是用于检查类型的简单本机PHP方法的集合,但是经过重写,因此它们属于类。 我不确定这背后的原因,因为API几乎完全相同( self::isArray() vs is_array() ),但是我认为它与保持组件可扩展性有关–能够更新这些组件无需更改整个lib库的API的本机方法就可以保证以后成为无价之宝。

In one part, the validator makes use of the StdObjectWrapper which is a part of the StdObject sub library – it uses the Webiny OO wrappers for scalars and the url format to provide a fluent interface for checking these types.

验证器在一部分中利用了StdObject子库的一部分StdObjectWrapper –它使用Webiny OO包装器来处理标量,并使用url格式来提供流利的接口来检查这些类型。

StdObjectTrait (StdObjectTrait)

This is the core of the StdLib component, the main part. It provides the class that uses this trait with the ability to spawn ArrayObject, UrlObject, StringObject and DateTimeObject instances by means of an appropriate helper method.

这是StdLib组件的核心, 主要部分 。 它为使用此特征的类提供了通过适当的辅助方法生成ArrayObject,UrlObject,StringObject和DateTimeObject实例的功能。

字符串对象 (StringObject)

Arguably the simplest of the bunch, this object allows you to use strings as objects.

可以说这是最简单的对象,该对象允许您将字符串用作对象。

$string = $this->str("My string");

The instance will natively contain an encoding constant (defaulting to UTF8) and some helper methods like length, wordCount and subStringCount, all of which are demonstrably useful, as well as some native PHP functions once again wrapped into class methods. Via a ManipulatorTrait, common to all the StdObjects, the StringObject also has access to methods that change it – trim being the most familiar one but also featuring those for appending, prepending, adding slashes, and much, much more.

该实例将本地包含一个编码常量(默认为UTF8)和一些辅助方法,如lengthwordCountsubStringCount ,所有这些方法都非常有用,还有一些原生PHP函数再次包装到类方法中。 通过ManipulatorTrait ,通用于所有StdObjects的StringObject还先后获得方法是改变它- trim是最熟悉的一个,但也配有那些附加的前面加上,加斜杠,等等,等等。

An enormous advantage of this approach is not only the ability to chain calls to the string object, but also the autocomplete such an interface provides for your IDE:

这种方法的巨大优势不仅在于可以将调用链接到字符串对象,而且还可以通过自动完成此类接口为您的IDE提供:

alt
$string = $this->str("This is a string");
echo $string->hash()->padLeft(45, "testing");

In one line, we hash the string and pad the remaining character slots on the left of it with the word “testing” until there are 45 characters. The result is testif72017485fbf6423499baf9b240daa14f5f095a1. It hardly gets simpler than that, and it’s extremely readable.

在一行中,我们对字符串进行哈希处理,并用单词“ testing”填充字符串左侧的其余字符,直到有45个字符为止。 结果是testif72017485fbf6423499baf9b240daa14f5f095a1 。 它几乎没有比这更简单的了,并且可读性强。

As another example, see this one from the docs:

再举一个例子,从文档中看到这个:

$string = new StringObject('Some test string.');
$string->caseUpper()->trimRight('.')->replace(' test'); // SOME STRING

Of course, the object implements the __toString method so that it’s directly usable as a string. Coincidentally, all other objects in the StdLib also implement this method, and are directly printable, producing the output you’d expect their non-object counterparts to generate.

当然,该对象实现了__toString方法,因此它可以直接用作字符串。 巧合的是,StdLib中的所有其他对象也都实现了此方法,并且可以直接打印,从而产生您希望非对象对应对象生成的输出。

The methods that are exposed are too numerous to name, so take a look at the file to find out about all of them.

公开的方法太多了,无法命名,因此请查看文件以查找所有这些方法。

数组对象 (ArrayObject)

Similar to StringObject, the ArrayObject offers an easy interface to array manipulation. Naturally, it’s iteration-friendly so you can just loop through it as through any array with a foreach, behaving almost like a native array.

与StringObject相似,ArrayObject为数组操作提供了一个简单的接口。 自然,它是迭代友好的,因此您可以像使用本机数组一样,通过带有foreach的任何数组来遍历它。

$array = new ArrayObject(['one', 'two', 'three']);
$array->first(); // StringObject 'one'
$array->append('four')->prepend('zero'); // ['zero', 'one', 'two', 'three', 'four']

Note that getting elements from this array format produces StdObjects, not actual scalars. The return value will always be of the StdObjectAbstract type. Strings produce StringObject, arrays produce ArrayObject, and numbers, curiously and somewhat both inconsistently and consistently produce an instance of StdObjectWrapper with the _value property set to the actual number. If the element is a class, that class gets wrapped with the wrapper, too. For example:

请注意,从此数组格式获取元素会生成StdObject,而不是实际的标量。 返回值将始终为StdObjectAbstract类型。 弦乐产生StringObject,阵列产生ArrayObject的,和数字,好奇,有点不一致都与持续生产的一个实例StdObjectWrapper_value属性设置为实际数量。 如果元素是一个类,则该类也将被包装器包装。 例如:

$array = $this->arr([1, "2", new myClass(1, 2)]);
var_dump($array->last());

This gives us:

这给我们:

alt

I’m not sure how I feel about this. On one hand, this is super consistent, making sure we always get the StdObjectWrapper in some shape or form, but on the other, if I’m dealing with an array of classes, I couldn’t care less about this wrapper. There is, of course, a way to get the real value out of any of the Webiny StdLib objects – each has a val method which pulls out the underlying value contained within.

我不确定我对此有何看法。 一方面,这是超级一致的,确保我们总是以某种形状或形式获取StdObjectWrapper ,但另一方面,如果我要处理一系列的类,那么我不会对此包装物有所关心。 当然,有一种方法可以从任何Webiny StdLib对象中获取实际值-每个对象都有一个val方法,该方法可以提取其中包含的基础值。

For all the various manipulative methods that arrays have access to by using this trait, see the manipulator. I find the chainable level syntax particularly useful – being able to go down into a multidimensional array by using key1.key2.key3 as an index is quite the impressive timesaver:

有关数组使用此特征可以访问的所有各种操作方法,请参见manipulator 。 我发现可链接级别的语法特别有用–通过使用key1.key2.key3作为索引进入多维数组非常key1.key2.key3时间:

$array = [
            'k1' => 'test',
            'k2' => [
                'k3' => [
                    'k4' => 'deepest'
                ]
            ]
        ];
        
$a = new ArrayObject($array);
$a->keyNested('k2.k3.k4', 'webiny');
$a->keyNested('k2.k3.k5', 'anotherElement');

echo $a->keyNested('k2.k3.k4'); // webiny
echo $a->keyNested('k2.k3.k5'); // anotherElement
URLObject (URLObject)

The URL object is here to make dealing with URL syntax easier. It supports some common response codes, methods for dealing with query params, ports, and other variables and can also be manipulated easily – switch out scheme, hosts, domains etc with a single line of reliable code.

URL对象用于简化URL语法的处理。 它支持一些常见的响应代码,用于处理查询参数,端口和其他变量的方法,并且还可以轻松地进行操作 -只需一行可靠的代码即可切换方案,主机,域等。

What’s strange is that URLObject doesn’t extend the StringObject. To me, extending would make sense seeing as they’re both, essentially, strings in this case and the former would benefit from the manipulative methods of the latter. There are also much better URL manipulation libraries out there, so I don’t see the benefit of using this one. One example that springs to mind is the excellent PHP League URL library which does all this and much, much more, with the added advantage of being fully tested and actively maintained by over a dozen of highly capable developers.

奇怪的是URLObject没有扩展StringObject。 对我而言,在这种情况下,扩展将是有道理的,因为它们本质上都是字符串,而前者将从后者的操作方法中受益。 还有更好的URL操作库,因此我看不到使用此库的好处。 一个令人印象深刻的例子就是出色的PHP League URL库 ,它不仅可以做所有这些事情而且还可以做更多的事情,另外还具有由十多个功能强大的开发人员进行全面测试和积极维护的额外优势。

DateTimeObject (DateTimeObject)

Finally, there’s the DateTimeObject. With helper methods bursting at the seams, the DateTime object provides a more fluent, natural interface to PHP’s native DateTime class and helps you deal with time-related problems:

最后,还有DateTimeObject。 随着辅助方法的突如其来,DateTime对象为PHP的本机DateTime类提供了更流畅,自然的接口,并帮助您处理与时间有关的问题:

$dt = new DateTimeObject('3 months ago');
echo $dt; // 2013-02-12 17:00:36
$dt->add('10 days')->sub('5 hours'); // 2013-02-22 12:00:36

In and of itself, the DateTimeObject trait is very handy if you’re already using StdLib in a project, but for any more complex DateTime manipulations, I would recommend Carbon with some Period added in for flavor.

就其本身而言,如果您已经在项目中使用StdLib,则DateTimeObject特性非常方便,但是对于任何更复杂的DateTime操作,我建议添加Carbon并添加一些Period来增加风味。

That’s not to say the DateTimeObject doesn’t have its use – it supports default time zones, easy date format outputs of various shapes and sizes, simple and easy diffs as a lighter alternative to Period, human readable “X time ago” outputs, offsetting to different timezones, and much more.

这并不是说DateTimeObject没有使用-它支持默认时区,各种形状和大小的简单日期格式输出,简单易用的diff作为Period的较轻替代品,人类可读的“ X time ago”输出,偏移量到不同的时区等等。

结论 (Conclusion)

By doing all this, the Webiny framework makes sure no developer coming into the project deals with native PHP types. They all have their appropriate wrappers and they all behave exactly as the developers want them to behave. Is this overly ambitious? Maybe. But I see it as an interesting approach akin to defining a coding standard before you start working on a project – the problems encountered during further stages of development will be domain specific exclusively, most likely saving time in the long run. The only big con I can see here is having to use the trait in every single class you want to give StdObject support to.

通过完成所有这些操作,Webiny框架可确保没有任何开发人员参与该项目来处理本机PHP类型。 它们都有合适的包装器,它们的行为完全符合开发人员想要的行为。 这太雄心勃勃吗? 也许。 但是,我认为这是一种有趣的方法,类似于在开始项目之前定义编码标准–在开发的进一步阶段遇到的问题将是特定于领域的,从长远来看很可能节省时间。 我在这里看到的唯一大缺点是必须在每个要为StdObject提供支持的类中use trait。

The Webiny project is an ambitious and interesting one. The scope of the framework is impressive and the ground its components cover vast – but whether or not they’re actually necessary, I’ll leave that up to you to decide. If you’re curious as to why I’m paying so much attention to this framework as to warrant a post (or several), it’s because I enjoy playing with new things, but also because I contributed to it a little bit and am curious as to where they can take it.

Webiny项目是一个雄心勃勃且有趣的项目。 该框架的范围令人印象深刻,其组成部分涵盖了广泛的基础,但是,不管它们是否确实必要,我将由您自己决定。 如果您对为什么我如此关注这个框架以至于需要发表一个(或多个)帖子感到好奇,那是因为我喜欢玩新事物,还因为我对此有所贡献并且感到好奇关于他们可以拿到哪里。

In some future posts, we’ll be looking at more Webiny components and even build a sample event driven application with the framework to take it for a proper spin and gauge its effectiveness. Until then, I encourage you to play around with its various aspects and tell us about your experiences.

在以后的一些文章中,我们将研究更多Webiny组件,甚至使用该框架构建示例事件驱动的应用程序,以使其适当旋转并评估其有效性。 在此之前,我鼓励您尝试各个方面,并向我们介绍您的经历。

翻译自: https://www.sitepoint.com/exploring-webiny-framework-stdlib-component/

stdlib

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值