I have a task to access an external API and then render the results to a separate FE. I have made an ApiClass and a ProductListClass. Then from an index page I am including the two class files and then am trying to call the ProductListClass method, but I am getting an ApiClass not found error and can't quite work out why.
Here's my 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);
}
}
This is my 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;
}
}
}
And this is the index page
<?php
include_once 'app/ProductListClass.php';
include_once 'app/ApiClass.php';
$api = new ApiClass();
$productList = new ProductList($api);
$productList->getList();
and this is the error I am getting
Fatal error: Uncaught Error: Class 'ApiClass' not found in /Applications/XAMPP/xamppfiles/htdocs/test/index.php:6 Stack trace: #0 {main} thrown in /Applications/XAMPP/xamppfiles/htdocs/test/index.php on line 6
You need to instantiate ApiClass from correct namespace, and fully qualified name (FQN) for your ApiClass
is app\ApiClass\ApiClass
. You need to either call
$api = app\ApiClass\ApiClass();
or use only class name by importing the namespace in the file header:
use app\ApiClass\ApiClass;
include_once 'app/ProductListClass.php';
include_once 'app/ApiClass.php';
$api = new ApiClass();
...
Namespaces are declared for each file, so that you could not change them by including files in different contexts. No namespace defined in the file means that it's global namespace (like your ProductListClass
).
If you're passing Client
instance to your ApiClass you need to have it already instantiated and there's no need to use new
on it again. If you take FQN string as a parameter you may do that, but that's not a good practice (unless you're doing this kind of magic in some dependency injection library).
So either do this (preferred):
class ApiClass
{
...
public function __construct(Client $client)
{
$this->url = 'http://external-api';
$this->client = $client;
}
with api instantiation:
$api = new ApiClient(new GuzzleHttp\Client());
Or instantiate inside constructor without parameters:
public function __construct()
{
$this->url = 'http://external-api';
$this->client = new GuzzleHttp\Client();
}
Ps. I think you should learn to use Composer and its autoloading (automatic include class files) - working with libraries (and your own classes) will be much easier.