首页 > 解决方案 > 在组合项目中实例化类的问题

问题描述

所以我有一个任务是访问一个外部 api,然后将结果呈现给一个单独的 FE。我制作了一个 ApiClass 和一个 ProductListClass。然后从索引页面中,我包含了两个类文件,然后我尝试调用 ProductListClass 方法,但是我得到了一个 ApiClass not found 错误并且不能完全弄清楚为什么,非常感谢任何帮助

这是我的 ApiClass

   <?php

namespace app\ApiClass;
use GuzzleHttp\Client;

class ApiClass
{
    protected $url;
    protected $client;

    public function __construct(Client $client)
    {
        $this->url = 'http://external-api';
        $this->client = new $client; //GuzzleHttp\Client
    }

    private function getResponse(string $uri = null)
    {
        $full_path = $this->url;
        $full_path .=$uri;
       $result = $this->client->get($full_path);
        return json_decode($result->getBody()->getContents(), true);
    }
    public function getData($uri)
    {
        return $this->getResponse($uri);
    }
}

这是我的 ProductListClass

<?php

include ("ApiClass.php");

class ProductList 
{ 
    private $apiClass;

    public function __construct(ApiClass $apiClass) {
        $this->apiClass = $apiClass;
    }

    public function getList() {
        $urlAppend = 'list';
        $list =  $this->api->getData($urlAppend);
        if(array_key_exists("error", $list)) {
            $this->getList();
        } else {
            return $list;
        }
    }
}

这是索引页

<?php

include_once 'app/ProductListClass.php';
include_once 'app/ApiClass.php';

$api = new ApiClass();

$productList = new ProductList($api);
$productList->getList();

这是我得到的错误

致命错误:未捕获的错误:在 /Applications/XAMPP/xamppfiles/htdocs/test/index.php:6 中找不到类“ApiClass”堆栈跟踪:在 /Applications/XAMPP/xamppfiles/htdocs/test/ 中抛出 #0 {main}第 6 行的 index.php

标签: phpoopguzzlecomposition

解决方案


您需要从正确的命名空间实例化 ApiClass,并为您的ApiClassis实例化完全限定名称 (FQN) app\ApiClass\ApiClass。您需要致电

$api = app\ApiClass\ApiClass();

或者通过在文件头中导入命名空间来仅使用类名:

use app\ApiClass\ApiClass;

include_once 'app/ProductListClass.php';
include_once 'app/ApiClass.php';

$api = new ApiClass();
...

为每个文件声明了命名空间,因此您无法通过在不同上下文中包含文件来更改它们。文件中未定义命名空间意味着它是全局命名空间(如您的ProductListClass)。

GuzzleHttp\客户端

如果您将Client实例传递给您的 ApiClass,您需要将其实例化,并且无需new再次使用它。如果您将 FQN 字符串作为参数,您可以这样做,但这不是一个好习惯(除非您在某些依赖注入库中使用这种魔法)。

所以要么这样做(首选):

class ApiClass
{
    ...
    public function __construct(Client $client)
    {
        $this->url = 'http://external-api';
        $this->client = $client;
    }

使用 api 实例化:

$api = new ApiClient(new GuzzleHttp\Client());

或者在没有参数的构造函数内部实例化:

    public function __construct()
    {
        $this->url = 'http://external-api';
        $this->client = new GuzzleHttp\Client();
    }

附言。我认为你应该学习使用Composer及其自动加载(自动包含类文件)——使用库(和你自己的类)会容易得多。


推荐阅读