How do I use Codeception unit tests with Slim Framework 3? - php

I have run into a few problems trying to make Codeception work with my Slim Framework project.
First, I cannot call a service/repository/model from a unit class without it being in the same namespace. When the tests are run, the following code block results in:
[Error] Class 'OMIS\Services\UserService' not found`
// tests
public function testUser()
{
$userService = new UserService();
$this->tester->assertNotNull($userService->find(1));
}
Secondly, I am trying to get Codeception to interact with a testing database I have set up. Because I am using Laravel's Eloquent ORM I thought that enabling the Laravel ORM module for Codeception in unit.suite.yml might work as there is no Slim module available for unit testing, but I get the following error when running the tests:
ExampleTest: UserPHP Fatal error: Class 'Symfony\Component\HttpKernel\Client' not found in /Users/me/dev/project/vendor/codeception/codeception/src/Codeception/Lib/Connector/Laravel5.php on line 13
Fatal error: Class 'Symfony\Component\HttpKernel\Client' not found in /Users/Me/dev/project/vendor/codeception/codeception/src/Codeception/Lib/Connector/Laravel5.php on line 13
Here is the relevant part of my bootstrap/app.php file
session_start();
require __DIR__ . '/../vendor/autoload.php';
// Load environment variables
$dotenv = new Dotenv(__DIR__.'/../');
$dotenv->load();
$container = require __DIR__.'/../config/container.php';
$app = $container->get(App::class);
$config = new Config(__DIR__.'/../config/database.php');
$db = $config->get('db');
$capsule = new Capsule();
$capsule->addConnection($db);
$capsule->setAsGlobal();
$capsule->bootEloquent();
require __DIR__.'/../config/dependencies.php';
require __DIR__.'/../config/services.php';
require __DIR__.'/../config/controllers.php';
require __DIR__ . '/../app/routes.php';
// Middleware

Related

Uncaught Error: Call to undefined method App\App::run() in Slim-4 php and php-di

While working with Slim and PHP-DI, got a warning saying
Uncaught Error: Call to undefined method App\App::run()
The code is as follows:
require __DIR__ . "/../vendor/autoload.php";
$app = new \DI\Bridge\Slim\Bridge;
$app->run();
In latest version of PHP-DI, there are some changes
DI\Bridge\Slim\App has changed to DI\Bridge\Slim\Bridge. So if you are using use DI\Bridge\Slim\App as DiBridge; may not work. Instead try use DI\Bridge\Slim\Bridge as DiBridge;
There is no $app->run() method defined in PHP-DI Bridge class, hence its undefined. Instead use $app->create() method.
Note
In order to use create() method on $app, make sure you have slim/psr7 installed, otherwise you may see a bloody red warning. If you dont have slim/psr7 installed use the following command to get it installed
composer require slim/psr7
So after making sure slim/psr7 is there, code must look as follows
require __DIR__ . "/../vendor/autoload.php";
$app = new \DI\Bridge\Slim\Bridge;
$app->create();

php error at runtime Interface 'Psr\Container\ContainerInterface' not found

I recently uploaded a new dependency to a PHP app I am working on and I am now continually getting the following error in Postman
Fatal error: Interface 'Psr\Container\ContainerInterface' not found in
/var/www/html/api/vendor/container-interop/container-interop/src/Interop/Container/ContainerInterface.php on line
13
I have updated composer as well as a multitude of other things and still cannot seem to pinpoint the issue. (Also not sure if it means the error is with the index.php file or the container.php file)
Here is the code from the container.interface.php file
<?php
/**
* #license http://www.opensource.org/licenses/mit-license.php MIT
(see the LICENSE file)
*/
namespace Interop\Container;
use Psr\Container\ContainerInterface as PsrContainerInterface;
/**
* Describes the interface of a container that exposes methods to
read its entries.
*/
interface ContainerInterface extends PsrContainerInterface
{
}
And here is the initial code from my index.php file
<?php
ini_set('display_errors', 1);
// Include the SDK using the Composer autoloader
require 'vendor/autoload.php';
use Kreait\Firebase\Factory;
use Kreait\Firebase\ServiceAccount;
// Includes ;
require_once( 'config/database.php' );
require_once( 'controller/base.php' );
//$app = new Slim\App();
$app = new Slim\App(['settings' => ['displayErrorDetails' => true]]);
$twilio = new Twilio\Rest\Client(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN);
$serviceAccount = ServiceAccount::fromJsonFile('my_file.json');
$firebase = (new Factory)->withServiceAccount($serviceAccount)-
>withDatabaseUri('my_firebase_website')->create();
Solution: I was utilizing filezilla to transfer updated dependencies from my vendor folder on my local machine & in the process I was downloaded the wrong autoload.php file

What is the minimum code to access Laravel's services without using HTTP/Console Kernels?

I need to access to my app services in a simple php script. I don't want to create a HTTP/Console kernel. If the following is the content test.php file in the app root, what else should I call to make it working?
require_once __DIR__ . "/vendor/autoload.php"; //composer
$app = new Illuminate\Foundation\Application(realpath(__DIR__));
$app->boot(); // not sure about this
$app->make('db')->table('user')->get()->toArray();
Currently I get the following error:
PHP Fatal error: Uncaught ReflectionException: Class db does not exist in foo\vendor\laravel\framework\src\Illuminate\Container\Container.php:752
Fatal error: Uncaught ReflectionException: Class db does not exist in foo\vendor\laravel\framework\src\Illuminate\Container\Container.php:752
After checking the source code it's clear that the Application class does not load all classes defined in the config/app.php file and either you have bootstrap it yourself of running bootstrap function of build-in kernel. So, If you create a php file with the following lines you can access all app dependencies without bothering creating artisan command to do your snippet codes directly in phpstorm.
require_once __DIR__ . "/vendor/autoload.php"; //composer
$app = new Illuminate\Foundation\Application(realpath(__DIR__));
// http Kernel yet have to be registered, perhaps a bad design issue.
$app->singleton(
Illuminate\Contracts\Http\Kernel::class,
App\Http\Kernel::class
);
$app->singleton(
Illuminate\Contracts\Console\Kernel::class,
App\Console\Kernel::class
);
// optional
$app->singleton(
Illuminate\Contracts\Debug\ExceptionHandler::class,
App\Exceptions\Handler::class
);
$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
$kernel->bootstrap();
// and playground is ready
$users= $app->make('db')->table('user')->get()->toArray();
or
require_once __DIR__ . "/vendor/autoload.php";
$app = include_once __DIR__.'/bootstrap/app.php';
$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
$kernel->bootstrap();
dd(app('db')->table('user')->count());

Composer autoloader not loading classes

I am building a tiny vanilla PHP application and need to implement an autoloader into the functionality as I want to ensure my application is coded in a clean and efficient manner. I have decided to use Composer for it's built in autoloading functionality and have installed this and created a composer.json file. I then ran:
composer install
I have a class that is namespaced under lib\DB as follows:
<?php
namespace lib;
class DB
{
.....
And am attempting to call this namespaced class using:
include_once('config.php');
use lib\DB;
function addProducts() {
try {
$db = DB::getInstance();
$connection = $db->getConnection();
This is throwing an error saying:
Fatal error: Uncaught Error: Class 'lib\DB' not found in /var/www/php-parser/index.php on line 9
I can see the autoload.php files has been generated inside the vendor folder so this is all ok. Is there something I have forgotten to do?
Thanks

Why Composer load ClassLoader in this way?

Open vendor/composer/autoload_real.php and look at this code:
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
When:
spl_autoload_register(array('ComposerAutoloaderInitf06647a07a90b762eb34553a7bce155e', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInitf06647a07a90b762eb34553a7bce155e', 'loadClassLoader'));
Why Composer do this? And not this:
require_once __DIR__ . '/ClassLoader.php';
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
The reason is that multiple autoloaders might be present concurrently in one process if for example you run phpunit installed via composer, then your test bootstrap file will also include your project class loader, and so if we did a simple require it would redefine the ClassLoader class and do a fatal error. Using require_once would not work either since the ClassLoader.php file is present twice (one in PHPUnit, one in the project) with different paths. PHP would still include each of these once, leading in class redefinition.
This could be fixed with a simple if (!class_exists()) {} around the require, but unfortunately that kind of conditional class definition messes up APC on high traffic sites so we had to resort to this strange temporary autoloader hack to make it work everywhere.

Categories