Issues instantiating class in composition project

Tags: , , ,



So 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 cant quite work out why, any help greatly appreciated

heres my ApiClass

   <?php

namespace appApiClass;
use GuzzleHttpClient;

class ApiClass
{
    protected $url;
    protected $client;

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

    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

Answer

You need to instantiate ApiClass from correct namespace, and fully qualified name (FQN) for your ApiClass is appApiClassApiClass. You need to either call

$api = appApiClassApiClass();

or use only class name by importing the namespace in the file header:

use appApiClassApiClass;

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).

GuzzleHttpClient

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 GuzzleHttpClient());

Or instantiate inside constructor without parameters:

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

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.



Source: stackoverflow