试图了解如何在命名空间中添加我自己的类

时间:2015-10-05 16:12:09

标签: php composer-php

我是使用作曲家的新手,因为Rachet和websockets引起了我的注意。我能够让Rachet websocket聊天应用程序工作,但现在我想在示例中使用我自己的类。

我的聊天示例here与这些名称更改具有相同的目录结构:

/src/MyApp/Chat.php = /src/Websocket/SocketControl.php

/bin/chat-server.php = /bin/socket-server.php

我的composer.json:

{
    "autoload": {
        "psr-0": {
            "Websocket": "src"
        }
    },
    "require": {
        "cboden/ratchet": "^0.3.3"
    }
}

在我的src文件夹中,我添加了一个文件夹MyClass,并且文件Foo.php如下所示:

<?php
class Foo{
    function __construct(){
        echo "Foo construct!\n";
    }
}

我如何能够在我的SocketControler中获得一个新的Foo,例如:

<?php
namespace Websocket;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;

class SocketControl implements MessageComponentInterface {
    protected $clients;
    protected $foo;

    public function __construct() {
        $this->clients = new \SplObjectStorage;
        $this->foo = new Foo();
        echo "New construct!\n";
    }

    public function onOpen(ConnectionInterface $conn) {
        // Store the new connection to send messages to later
        $this->clients->attach($conn);

        echo "New connection! ({$conn->resourceId})\n";
    }

    public function onMessage(ConnectionInterface $from, $msg) {
        $numRecv = count($this->clients) - 1;
        echo sprintf('Connection %d sending message "%s" to %d other connection%s' . "\n"
            , $from->resourceId, $msg, $numRecv, $numRecv == 1 ? '' : 's');

        foreach ($this->clients as $client) {
            if ($from !== $client) {
                // The sender is not the receiver, send to each client connected
                $client->send($msg);
            }
        }
    }

    public function onClose(ConnectionInterface $conn) {
        // The connection is closed, remove it, as we can no longer send it messages
        $this->clients->detach($conn);

        echo "Connection {$conn->resourceId} has disconnected\n";
    }

    public function onError(ConnectionInterface $conn, \Exception $e) {
        echo "An error has occurred: {$e->getMessage()}\n";

        $conn->close();
    }
}

1 个答案:

答案 0 :(得分:2)

一件事是:您确定了解PHP命名空间的工作原理吗?因为自动加载是另一回事,并且首先使事情有效,您也可以使用旧式require_once()来查看代码是否有效或存在问题。

自动加载本身应该非常简单,但是如果你没有让你的命名空间问题变得紧张,它会让你感到困惑。问题不在于自动加载不起作用,而是您的代码请求一个无法自动加载的类名,因为类本身被命名为错误。

例如,在您的代码中,您位于名称空间“Websocket”内,并且具有此代码new Foo()。这将尝试自动加载类Websocket\Foo。你有这堂课吗?没有!您有class Foo...,但未将namespace Websocket;作为第一个代码行。

自动加载会告诉您PHP无法加载Websocket\Foo,但为什么?您的自动加载定义是这样说的:每个以名称空间Websocket\开头的类都位于路径“src /”中。因此,PSR-4创建路径“src / Foo.php”以查找Websocket\Foo。但是,该文件中的代码不会声明这样的类!它在全局命名空间中声明\Foo。执行该文件后,没有定义类Websocket\Foo,这将使代码失败。

请注意,PHP命名空间和文件系统布局之间没有直接连接。从理论上讲,您可以将各种命名空间分布在任何类型的文件布局中。为了方便起见,选择类名称与路径名称的1:1映射 - 它不是由PHP强制执行,也不保证在自动加载代码时起作用,即在正确位置的代码文件仍然必须在内部具有正确的代码坚持承诺宣布一个正确的名称。