在PHP中构造数据类型?

时间:2010-10-05 06:41:44

标签: php

任何人都可以给我php中的结构数据类型的例子吗?为什么突然间会出现类似于结构的结构?

7 个答案:

答案 0 :(得分:88)

最接近结构是一个公共所有成员的对象。

class MyStruct {
    public $foo;
    public $bar;
}

$obj = new MyStruct();
$obj->foo = 'Hello';
$obj->bar = 'World';

我会说看PHP Class Documentation是值得的。 如果您需要一次性结构use the StdObject as mentioned in alex's answer

答案 1 :(得分:43)

您可以使用数组

$something = array(
   'key' => 'value',
   'key2' => 'value2'
);
带有标准对象的

$something = new StdClass();

$something->key = 'value';
$something->key2 = 'value2';

答案 2 :(得分:2)

我今天拼凑了一个'动态'结构类,今晚看了一下,有人写了类似的东西,更好地处理构造函数参数,可能值得一看:

http://code.activestate.com/recipes/577160-php-struct-port/

本页面上的一条评论提到了PHP中一件有趣的事情 - 显然你可以将一个数组转换为一个对象,这可以让你使用箭头符号引用数组元素,就像使用一个Struct指针一样C.评论的例子如下:

$z = array('foo' => 1, 'bar' => true, 'baz' => array(1,2,3));
//accessing values as properties
$y = (object)$z;
echo $y->foo;

我自己还没有尝试过这个,但可能是你可以通过演员获得所需的乐谱 - 如果这就是你所追求的全部。这些当然是“动态”数据结构,只是用于访问散列中的键/值对的语法糖。

如果你真的想找一些更静态输入的东西,那么ASpencer的答案就是你正在寻找的机器人(正如欧比万所说的那样)。

答案 3 :(得分:2)

似乎struct数据类型在SOAP 中常用

var_dump($client->__getTypes());

array(52) {
  [0] =>
  string(43) "struct Bank {\n string Code;\n string Name;\n}"
}

这不是本机PHP数据类型!

似乎SOAP中引用的struct类型的属性可以作为简单的PHP stdClass对象访问:

$some_struct = $client->SomeMethod();
echo 'Name: ' . $some_struct->Name;

答案 4 :(得分:1)

我推荐两件事。首先是关联数组

$person = Array();
$person['name'] = "Joe";
$person['age'] = 22;

其次是

此处的详细文档:http://php.net/manual/en/language.oop5.php

答案 5 :(得分:0)

PHP中只有关联数组是结构。

您不能对它们进行严格限制。

但是您可以使用类和接口对结构进行严格的伪造,但要注意,class instances are not passed in arguments, their identifiers are与结构不同!


您可以通过接口(或至少靠近接口)定义结构

结构在对象上强制执行某种结构。

PHP(<= 7.3)没有本机结构,但是您可以使用接口和类型提示来解决它:

interface FooStruct 
{
    public function name() : string;
}
interface BarStruct 
{
    public function id() : int;
}
interface MyStruct 
{
   public function foo() : FooStruct;
   public function bar() : BarStruct;
}

任何实现MyStruct的类都将是MyStruct

其构建方式不取决于结构,它只是确保返回的数据正确。


如何设置数据?

设置结构数据是有问题的,因为我们最终会遇到getter和setter,而且它接近anemic objectDTOconsidered an anti-pattern by some people

错误的示例:

interface FooStruct 
{
    public function getName() : string;
    public function setName(string $value) : FooStruct;
}
interface BarStruct 
{
    public function getId() : int;
    public function setId(int $value) : BarStruct;
}
interface MyStruct 
{
   public function getFoo() : FooStruct;
   public function setFoo(FooStruct $value) : MyStruct;
   public function getBar() : BarStruct;
   public function setBar(BarStruct $value) : MyStruct;
}

然后,我们最终得到的类实现可能是可变的,并且结构不得突变,这是使其成为“数据类型”,就像intstring一样。 但是,没有办法用PHP中的接口来限制它,这意味着人们将能够在不是结构的类中实现您的结构接口。 确保保留实例immutable

然后在没有正确数据的情况下实例化结构,并在尝试访问数据时触发错误。

在PHP struct类中设置数据的一种简单可靠的方法是通过其构造函数

interface FooStruct 
{
    public function name() : string;
}
interface BarStruct 
{
    public function id() : int;
}
interface MyStruct 
{
   public function foo() : FooStruct;
   public function bar() : BarStruct;
}

class Foo implements FooStruct 
{
   protected $name;
   public function __construct(string $name)
   {
       $this->name = $name;
   }
   public function name() : string
   {
       return $this->name;
   }
}

class Bar implements BarStruct 
{
   protected $id;
   public function __construct(string $id)
   {
       $this->id = $id;
   }
   public function id() : int
   {
       return $this->id;
   }
}

class My implements MyStruct 
{
   protected $foo, $bar;
   public function __construct(FooStruct $foo, BarStruct $bar)
   {
       $this->foo = $foo;
       $this->bar = $bar;
   }
   public function foo() : FooStruct
   {
       return $this->foo;
   }
   public function bar() : BarStruct
   {
       return $this->bar;
   }
}

使用接口的类型提示:(如果您的IDE支持)

如果您不介意不进行严格的类型检查,那么另一种方法是使用带有注释的接口或类作为IDE。

/**
 * Interface My
 * @property Foo $foo
 * @property Bar $bar
 */
interface My 
{

}

/**
 * Interface Foo
 * @property string|integer $id
 * @property string $name
 */
interface Foo 
{

}

/**
 * Interface Bar
 * @property integer $id
 */
interface Bar
{

}

使用接口而不是类的原因与最初存在接口的原因相同,因为那时具有许多实现的许多类可以具有相同的结构,并且使用该接口的每个方法/函数都将为此支持每个类界面。

这取决于您的IDE,因此您可能需要改用类,或者只是不使用它而生活。

注意: 请记住,您必须在代码中其他地方验证/清除实例中的数据以匹配注释。

答案 6 :(得分:0)

公共类是一个选择,如果您想封装更多内容,可以使用抽象/匿名类组合。我最喜欢的部分是,自动完成仍然可以(对于PhpStorm)起作用,但是我没有公开课。

<?php

final class MyParentClass
{
    /**
     * @return MyStruct[]
     */
    public function getData(): array
    {
        return array(
            $this->createMyObject("One", 1.0, new DateTime("now")),
            $this->createMyObject("Two", 2.0, new DateTime("tommorow"))
        );
    }

    private function createMyObject(string $description, float $magnitude, DateTime $timeStamp): MyStruct
    {
        return new class(func_get_args()) extends MyStruct {
            protected function __construct(array $args)
            {
                $this->description = $args[0];
                $this->magnitude = $args[1];
                $this->timeStamp = $args[2];
            }
        };
    }
}

abstract class MyStruct
{
    public string $description;
    public float $magnitude;
    public DateTime $timeStamp;
}