【问题标题】:trying to use a trait but keeps saying not found试图使用一个特征,但一直说没有找到
【发布时间】:2019-11-05 15:41:38
【问题描述】:

我有一个连接到外部端点的 api 特征。我想在一个名为 ProductClass 的类中使用这个特性。该特征与该类位于同一文件夹中,但出现错误是我在类中添加了 use ApiTrait 。错误说它找不到特征,所以如果我在类文件的顶部包含特征文件,我会收到这个错误,找不到 ApiTrait 产品类\ApiTrait。 如果我将特征传递给构造函数,当我调用 ProductClass 时,我的索引页面会出现错误,因为我没有传递特征。我不想将任何参数传递给构造函数,只是将字符串顶部附加到 .env 端点。任何线索都非常感谢 这是我的 ApiTrait 代码

<?php
namespace ApiTrait;

require './vendor/autoload.php';
use GuzzleHttp\Client;

trait ApiTrait
{
    protected $url;
    protected $client;

  public function __construct()
  {
    $this->url =  getenv('API_URL');
    $this->client = new Client();

  }

  private function getResponse(String $uri = null)
  {
    $full_path = $this->url;
    $full_path .=$uri;
    try {
        $response = $this->client->get($full_path);    
    }
    catch (GuzzleHttp\Exception\ClientException $e) {
        $response = $e->getResponse();
    }
    return json_decode($response->getBody()->getContents(), true);

  }
  public function getAPIData($uri)
  {
    return $this->getResponse($uri);
  }
}

这是我的 ProductClass 代码

<?php

namespace ProductClass;
include_once("ApiTrait.php");

use DataInterface\DataInterface;

class Product implements DataInterface
{ 
    use ApiTrait\ApiTrait
    private $api;

    public function __construct(ApiTrait\ApiTrait $apiTrait) {
       $this->api = $apiTrait;
    }

    private function getResponse($append, $try) {
        $urlAppend = $append; 
        $good_data = false;

        do{
          try{
            $result = $this->api->getAPIData($urlAppend);
            //check data to see if valid
            if(!array_key_exists( "error",$result)){
                $good_data = true;
                return $result;
            }
          }
          catch(Exception $e){
            //call api upto 10 times
            if($try < 10) {
                sleep(1);
                getData($append, $try++);
            } else { //return a connection  error
                $api_error['error']='unable to connect to api';
                return  $api_error;
            }
        }
      } while($good_data === false);
  }

  public function getData($append, $try = 0)
  {
     return $this->getResponse($append, $try);
  }

}

【问题讨论】:

  • 你不能在构造函数中传递特征,这只是语法错误

标签: php class oop traits


【解决方案1】:

如果您使用的是自动加载器,则永远不需要这个:

include_once("ApiTrait.php");

你已经在 ApiTrait 命名空间中定义了你的特征:

namespace ApiTrait;
trait ApiTrait { ... }

即,特征的完整路径是\ApiTrait\ApiTrait。如果您在命名空间中使用该特征而不是它定义的命名空间,那么您需要在引用它时从根命名空间锚定,在它前面加上一个反斜杠:

namespace ProductClass;
class Product implements DataInterface
{ 
    use \ApiTrait\ApiTrait;

否则,如果您在没有前导反斜杠的情况下执行 use ApiTrait\ApiTrait;,则 PHP 认为您指的是当前命名空间,即 ProductClass,产生 \ProductClass\ApiTrait\ApiTrait——它不存在,因此您的错误。

你也可以使用类别名来做到这一点:

namespace ProductClass;
use ApiTrait\ApiTrait;
class Product implements DataInterface
{ 
    use ApiTrait;

此外,您似乎只是将每个类都放在了自己的命名空间中。不要那样做。使用命名空间对常见项目进行分组,例如,如下所示:

namespace Traits;
trait Api { ... }

namespace Traits;
trait Foo { ... }

namespace Traits;
trait Bar { ... }

namespace App;
class Product {
    use \Traits\Api;
    use \Traits\Foo;
    use \Traits\Bar;
}

【讨论】:

  • 我认为我从未在 use 语句中使用过斜杠。
  • 可能是因为你在类定义之前做了一个use Foo\Bar\Trait 别名声明(它已经被定义为根锚定了),然后只是在类中的简短形式use Trait
  • 我只在顶部使用它,是的。第三段似乎建议您在使用名称空间的任何地方都需要斜杠。至少我是这样读的。
  • 我认为您将类别名声明与特征使用声明混淆了。类定义之外的 use 关键字是别名声明,并且从不具有前面的反斜杠。类定义中的use 关键字是一个特征声明。如果你没有使用前面的反斜杠,那么你要么需要在定义特征的同一个命名空间中,要么已经通过上述使用 use 关键字为其声明了别名。
  • 如果你在一个命名空间中使用这个特征,而不是它定义的命名空间,那么你需要在引用它时从根命名空间锚定,在它前面加上一个反斜杠: 阅读本文时,我的印象是,如果命名空间中的第一个根与当前根不同,则需要前导斜杠。确实如此,除非它是在文件顶部使用标准使用语句(导入、解析)导入的,该语句不会指定前导斜杠。
猜你喜欢
  • 1970-01-01
  • 2018-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-31
  • 2021-01-19
  • 1970-01-01
相关资源
最近更新 更多