So I have an App\bindings.php file that I have added to my composer.json file as so:
"autoload": {
"files": [
"app/bindings.php"
]
},
In this file I am trying to set up bindings for my repositories like so:
<?php
function getRepoBinding($id)
{
$repo = "{$id}Repository";
$clientName = strtoupper(config('client.name'));
$implementation = config('app.repo_implementation', 'Eloquent');
$clientOverride = "App\Overrides\\{$clientName}\Repositories\\{$implementation}\\{$repo}";
$repo = class_exists($clientOverride) ? $clientOverride : "App\Repositories\\{$implementation}\\{$repo}";
return $repo;
}
// Repository Interface Bindings
dd(getRepoBinding('Contribution'));
App::bind('ContributionIneterface', getRepoBinding('Contribution'));
However, i run a composer dump-auto and try to run my application and I get the following error:
Fatal error: Uncaught Error: Call to a member function make() on null in /home/vagrant/Code/famsapi/vendor/laravel/framework/src/Illuminate/Foundation/helpers.php:54
Stack trace: #0 /home/vagrant/Code/famsapi/vendor/laravel/framework/src/Illuminate/Foundation/helpers.php(158): app('config')
#1 /home/vagrant/Code/famsapi/app/bindings.php(9): config('client.name')
#2 /home/vagrant/Code/famsapi/app/bindings.php(16): App\getRepoBinding('Contribution')
#3 /home/vagrant/Code/famsapi/vendor/composer/autoload_real.php(55): require('/home/vagrant/C...')
#4 /home/vagrant/Code/famsapi/vendor/composer/autoload_real.php(45): composerRequire03fe235c8b3156f0c5fcebbc0d696734('90f93262f3a0ac8...', '/home/vagrant/C...')
#5 /home/vagrant/Code/famsapi/vendor/autoload.php(7): ComposerAutoloaderInit03fe235c8b3156f0c5fcebbc0d696734::getLoader()
#6 /home/vagrant/Code/famsapi/bootstrap/autoload.php(17): require('/home/vagrant/C...')
#7 /home/vagrant/Code/famsapi/public/index.php(22): require('/home/vagrant/C...')
#8 {main} thrown in /home/vagrant/Code/famsapi/vendor/laravel/framework/src/Illuminate/Foundation/helpers.php on line 54
It seems like it is having with the global config helper method...but im not sure how to fix that. Better yet, if you have an idea of how I can do this another way I am all ears.
It is because you are loading that file before the application starts.
Use it inside your AppServiceProvider
Related
I am trying a simple Slim application as shown below.
index.php
<?php
use Slim\Factory\AppFactory;
require './vendor/autoload.php';
$app = AppFactory::create();
$app->get('/', [TestController::class, 'showBlank']);
$app->run();
And below is the TestController.php.
<?php
use \Psr\Container\ContainerInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\Http\Interfaces\ResponseInterface;
class TestController
{
protected $c;
public function __construct(ContainerInterface $c)
{
$this->c = $c;
}
public function showBlank(ServerRequestInterface $request, ResponseInterface $response, array $args): ResponseInterface
{
return $response;
}
}
Below is the project structure.
C:\laragon\www\chum>ls
composer.json composer.lock index.php TestController.php vendor
Since I am trying slim for first time, I am keep the example to very minimal and so the composer.json file.
{
"require": {
"slim/slim": "^4.11",
"slim/psr7": "^1.6",
"slim/twig-view": "^3.3",
"slim/http": "^1.3"
}
}
Given these, I am getting the below exceptio when I try to access the root page(\).
Fatal error: Uncaught RuntimeException: Callable TestController::showBlank() does not exist in C:\laragon\www\chum\vendor\slim\slim\Slim\CallableResolver.php:138
Stack trace:
#0 C:\laragon\www\chum\vendor\slim\slim\Slim\CallableResolver.php(90): Slim\CallableResolver->resolveSlimNotation('TestController:...')
#1 C:\laragon\www\chum\vendor\slim\slim\Slim\CallableResolver.php(63): Slim\CallableResolver->resolveByPredicate('TestController:...', Array, 'handle')
#2 C:\laragon\www\chum\vendor\slim\slim\Slim\Routing\Route.php(340): Slim\CallableResolver->resolveRoute(Array)
#3 C:\laragon\www\chum\vendor\slim\slim\Slim\MiddlewareDispatcher.php(65): Slim\Routing\Route->handle(Object(Slim\Http\ServerRequest))
#4 C:\laragon\www\chum\vendor\slim\slim\Slim\MiddlewareDispatcher.php(65): Slim\MiddlewareDispatcher->handle(Object(Slim\Http\ServerRequest))
#5 C:\laragon\www\chum\vendor\slim\slim\Slim\Routing\Route.php(315): Slim\MiddlewareDispatcher->handle(Object(Slim\Http\ServerRequest))
#6 C:\laragon\www\chum\vendor\slim\slim\Slim\Routing\RouteRunner.php(68): Slim\Routing\Route->run(Object(Slim\Http\ServerRequest))
#7 C:\laragon\www\chum\vendor\slim\slim\Slim\MiddlewareDispatcher.php(65): Slim\Routing\RouteRunner->handle(Object(Slim\Http\ServerRequest))
#8 C:\laragon\www\chum\vendor\slim\slim\Slim\App.php(199): Slim\MiddlewareDispatcher->handle(Object(Slim\Http\ServerRequest))
#9 C:\laragon\www\chum\vendor\slim\slim\Slim\App.php(183): Slim\App->handle(Object(Slim\Http\ServerRequest))
#10 C:\laragon\www\chum\index.php(56): Slim\App->run() #11 {main} thrown in C:\laragon\www\chum\vendor\slim\slim\Slim\CallableResolver.php on line 138
Thanks Alvaro for the great tips in comments, I was able to solve it with some further help from Google based on that.
I was under assumption flat project structure does not need namespaces to be configured. But I was wrong.
I did the below updates to composer.json file and ran composer dump-autoload -o.
"autoload": {
"psr-4": {
"App\\": ""
}
},
yii2 advanced
I have created a Controller - console/components/OneController.php
//One
namespace console\controllers;
use Yii;
use yii\console\Controller;
Class OneController extends Controller{
public function actionIndex(){
echo 'one!';
return true;
}
}
//command in console:
php yii one
//result:
one!
its working!
I am creating my folder for my test controllers - components
I am creating my Controller - console/components/TwoController.php
//Two
namespace console\controllers;
use Yii;
use yii\console\Controller;
Class TwoController extends Controller{
public function actionIndex(){
echo 'two!';
return true;
}
}
console\config\main-local.php
'controllerMap' => [
'fixture' => [
'class' => 'yii\console\controllers\FixtureController',
'namespace' => 'common\fixtures',
],
'two' => [
'class' => 'yii\console\components\TwoController',//++
],
],
//command in console:
php yii two
its not working. How to run my Controller in my Folder?
Administrator#WIN-XXXXXXXXXXX c:\Administrator\OpenServer\OpenServer\domains\mysite.us
$ php yii two
An Error occurred while handling another error:
exception 'ReflectionException' with message 'Class yii\console\components\TwoController does not exist' in C:\Administrator\OpenServer\OpenServer\domains\mysite.us\vendor\yiisoft\yii2\di\Container.php:424
Stack trace:
#0 C:\Administrator\OpenServer\OpenServer\domains\mysite.us\vendor\yiisoft\yii2\di\Container.php(424): ReflectionClass->__construct('yii\\console\\com...')
#1 C:\Administrator\OpenServer\OpenServer\domains\mysite.us\vendor\yiisoft\yii2\di\Container.php(364): yii\di\Container->getDependencies('yii\\console\\com...')
#2 C:\Administrator\OpenServer\OpenServer\domains\mysite.us\vendor\yiisoft\yii2\di\Container.php(156): yii\di\Container->build('yii\\console\\com...', Array, Array)
#3 C:\Administrator\OpenServer\OpenServer\domains\mysite.us\vendor\yiisoft\yii2\BaseYii.php(344): yii\di\Container->get('yii\\console\\com...', Array, Array)
#4 C:\Administrator\OpenServer\OpenServer\domains\mysite.us\vendor\yiisoft\yii2\base\Module.php(578): yii\BaseYii::createObject(Array, Array)
#5 C:\Administrator\OpenServer\OpenServer\domains\mysite.us\vendor\yiisoft\yii2\console\UnknownCommandException.php(79): yii\base\Module->createController('test')
#6 C:\Administrator\OpenServer\OpenServer\domains\mysite.us\vendor\yiisoft\yii2\console\ErrorHandler.php(35): yii\console\UnknownCommandException->getSuggestedAlternatives()
#7 C:\Administrator\OpenServer\OpenServer\domains\mysite.us\vendor\yiisoft\yii2\base\ErrorHandler.php(111): yii\console\ErrorHandler->renderException(Object(yii\console\UnknownCommandException))
#8 [internal function]: yii\base\ErrorHandler->handleException(Object(yii\console\UnknownCommandException))
#9 {main}
Previous exception:
exception 'yii\base\InvalidRouteException' with message 'Unable to resolve the request "two".' in C:\Administrator\OpenServer\OpenServer\domains\mysite.us\vendor\yiisoft\yii2\base\Module.php:532
Stack trace:
#0 C:\Administrator\OpenServer\OpenServer\domains\mysite.us\vendor\yiisoft\yii2\console\Application.php(180): yii\base\Module->runAction('two', Array)
#1 C:\Administrator\OpenServer\OpenServer\domains\mysite.us\vendor\yiisoft\yii2\console\Application.php(147): yii\console\Application->runAction('two', Array)
#2 C:\Administrator\OpenServer\OpenServer\domains\mysite.us\vendor\yiisoft\yii2\base\Application.php(380): yii\console\Application->handleRequest(Object(yii\console\Request))
#3 C:\Administrator\OpenServer\OpenServer\domains\mysite.us\yii(27): yii\base\Application->run()
#4 {main}
Next exception 'yii\console\UnknownCommandException' with message 'Unknown command "two".' in C:\Administrator\OpenServer\OpenServer\domains\mysite.us\vendor\yiisoft\yii2\console\Application.php:183
Stack trace:
#0 C:\Administrator\OpenServer\OpenServer\domains\mysite.us\vendor\yiisoft\yii2\console\Application.php(147): yii\console\Application->runAction('two', Array)
#1 C:\Administrator\OpenServer\OpenServer\domains\mysite.us\vendor\yiisoft\yii2\base\Application.php(380): yii\console\Application->handleRequest(Object(yii\console\Request))
#2 C:\Administrator\OpenServer\OpenServer\domains\mysite.us\yii(27): yii\base\Application->run()
#3 {main}
I have the problem to use Slim/Flash/Messages, to do a flash message. I have this error
Fatal error:
Uncaught DI\NotFoundException: No entry or class found for 'Slim\Flash' in C:\laragon\www\cart\vendor\php-di\php-di\src\DI\Container.php:119
Stack trace:
#0 C:\laragon\www\cart\app\container.php(52): DI\Container->get('Slim\\Flash')
#1 [internal function]: DI\Definition\Source\DefinitionFile->{closure}(Object(DI\Container)) #2 C:\laragon\www\cart\vendor\php-di\invoker\src\Invoker.php(82): call_user_func_array(Object(Closure), Array)
#3 C:\laragon\www\cart\vendor\php-di\php-di\src\DI\Definition\Resolver\FactoryResolver.php(81): Invoker\Invoker->call(Object(Closure), Array)
#4 C:\laragon\www\cart\vendor\php-di\php-di\src\DI\Definition\Resolver\ResolverDispatcher.php(58): DI\Definition\Resolver\FactoryResolver->resolve(Object(DI\Definition\FactoryDefinition), Array)
#5 C:\laragon\www\cart\vendor\php-di\php-di\src\DI\Container.php(285): DI\Definition\Resolver\ResolverDispatcher->resolve(Object(DI\Definition\FactoryDefinition), Array)
#6 C:\laragon\www\cart\vendor\php-di\php-di\src\DI\Container.php(122): DI\Contai in C:\laragon\www\cart\vendor\php-di\php-di\src\DI\Container.php on line 119
In the bootstrap/app.php
$container->set('flash', function($container) {
return new \Slim\Flash\Messages($container);
});
in the container.php
Twig::class => function (ContainerInterface $c) {
$twig = Factory::getEngine();
$twig->addExtension(new TwigExtension(
$c->get('router'),
$c->get('request')->getUri()
));
$twig->getEnvironment()->addGlobal('basket', $c->get(Basket::class));
$twig->getEnvironment()->addGlobal('auth', $c->get(Auth::class));
$twig->getEnvironment()->addGlobal('user', $c->get(Customer::class));
$twig->getEnvironment()->addGlobal('flash', $c->get(Flash::class));
return $twig;
},
$twig->getEnvironment()->addGlobal('flash', $c->get(Flash::class)); means that you're looking for a key called Slim\Flash within the container, but you registered it with the key flash.
Therefore change:
$twig->getEnvironment()->addGlobal('flash', $c->get(Flash::class));
to
$twig->getEnvironment()->addGlobal('flash', $c->get('flash'));
Alternatively, you can use the fully qualified class name everywhere:
app.php:
use Slim\Flash\Messages as Flash;
$container->set(Flash::class, function($container) {
return new Flash($container);
});
and add this to the top of container.php:
use Slim\Flash\Messages as Flash;
I haven't quite got my head around namespaces in PHP yet. Nor do I use composer or autoloaders. I understand them, but often have difficulty including them into my own projects.
So I would like to include a package in a Wordpress plugin I am developing, specifically this one https://github.com/elliotboney/thinkific-php
I can include the main file OK, but get the error below when calling a function within that file. I am not sure if its to do with the fact its using namespaces, or just because its trying to include files in the Api sub folder which wont be the correct path once I include the main file into my own code.
Does anyone know how I can include this package to use it it within my own project?
require_once('Thinkific/Thinkific.php');
$think = new \Thinkific\Thinkific([
'apikey' => 'xxxxxxxxx',
'subdomain' => 'yyyyyyyyy',
'debug' => true
]);
$users = $think->users();
$users = $users->getAll();
But this is the error, which shows that the class files and so classes in the Api sub-folder are not loaded.
Fatal error: Uncaught Error: Class '\Thinkific\Api\Users' not found in Fatal error: Uncaught Error: Class '\Thinkific\Api\Users' not found in /mysite/public_html/wp-content/plugins/thinkific/Thinkific/Thinkific.php:51 Stack trace: #0 /mysite/public_html/wp-content/plugins/thinkific/Thinkific/Thinkific.php(36): Thinkific\Thinkific->getApi('\\Thinkific\\Api\\...') #1 /mysite/public_html/wp-content/plugins/thinkific/thinkific.php(50): Thinkific\Thinkific->__call('users', Array) #2 /mysite/public_html/wp-content/plugins/thinkific/thinkific.php(29): Thinkific::thinkific_get_users() #3 /mysite/public_html/wp-includes/class-wp-hook.php(298): thinkific_woocommerce_order_status_completed(Object(WP)) #4 /mysite/public_html/wp-includes/class-wp-hook.php(323): WP_Hook->apply_filters('', Array) #5 /mysite/public_html/wp-includes/plugin.php(515): WP_Hook->do_action(Array) #6 /mysite/public_html/wp-includes/class-wp.php(746): do_action_ref_array('wp in /mysite/public_html/wp-content/plugins/thinkific/Thinkific/Thinkific.php on line 51
Try something like this:
lib.php:
<?php
// Application library 1
namespace App\Lib1;
const MYCONST = 'Hello,';
// Application library 1
namespace App\Lib2;
const MYCONST = 'How are you?';
function MyFunction() {
return __FUNCTION__;
}
class MyClass {
static function WhoAmI() {
return __METHOD__;
}
}
?>
myapp.php:
<?php
require_once('lib.php');
echo App\Lib1\MYCONST . "\n";
echo App\Lib2\MYCONST . "\n\n";
echo App\Lib2\MyFunction() . "\n";
echo App\Lib2\MyClass::WhoAmI() . "\n";
?>
The library which you are using is dependent on composer, the place where you doing composer install there it will generate a vendor/autoload.php, you just need to generate vendor/autoload.php here this file will take care of your autoloading of classes.
require_once 'vendor/autoload.php';
$think = new \Thinkific\Thinkific([
'apikey' => 'xxxxxxxxx',
'subdomain' => 'yyyyyyyyy',
'debug' => true
]);
$users = $think->users();
$users = $users->getAll();
I have a method where I've set the type of first argument to be passed (array):
public function create(array $values, $options=array())
{
// set datetime columns
if(! isset($values['date_created']) or empty($values['date_created'])) {
$values['date_created'] = date("Y-m-d H:i:s");
}
if(! isset($values['date_updated']) or empty($values['date_updated'])) {
$values['date_updated'] = date("Y-m-d H:i:s");
}
return parent::create($values);
}
How do I test this using PHPUnit, it keeps throwing a fatal error which I guess is to be expected but it doesn't allow my script to run:
1) UserTableTest::testCreateMethodWithInvalidArguments
Failed asserting that exception of type "PHPUnit_Framework_Error" matches expected exception "InvalidArgumentException". Message was: "Argument 1 passed to app\models\UserTable::create() must be of the type array, string given, called in /var/www/phpdev/tests/models/UserTableMockTest.php on line 82 and defined" at
#0 /var/www/phpdev/app/models/UserTable.php(16): PHPUnit_Util_ErrorHandler::handleError(4096, 'Argument 1 pass...', '/var/www/phpdev...', 16, Array)
#1 /var/www/phpdev/tests/models/UserTableMockTest.php(82): app\models\UserTable->create('invalid argumen...')
#2 [internal function]: UserTableTest->testCreateMethodWithInvalidArguments()
#3 /var/www/phpdev/vendor/phpunit/phpunit/src/Framework/TestCase.php(962): ReflectionMethod->invokeArgs(Object(UserTableTest), Array)
#4 /var/www/phpdev/vendor/phpunit/phpunit/src/Framework/TestCase.php(826): PHPUnit_Framework_TestCase->runTest()
#5 /var/www/phpdev/vendor/phpunit/phpunit/src/Framework/TestResult.php(686): PHPUnit_Framework_TestCase->runBare()
#6 /var/www/phpdev/vendor/phpunit/phpunit/src/Framework/TestCase.php(760): PHPUnit_Framework_TestResult->run(Object(UserTableTest))
#7 /var/www/phpdev/vendor/phpunit/phpunit/src/Framework/TestSuite.php(699): PHPUnit_Framework_TestCase->run(Object(PHPUnit_Framework_TestResult))
#8 /var/www/phpdev/vendor/phpunit/phpunit/src/TextUI/TestRunner.php(426): PHPUnit_Framework_TestSuite->run(Object(PHPUnit_Framework_TestResult))
#9 /var/www/phpdev/vendor/phpunit/phpunit/src/TextUI/Command.php(179): PHPUnit_TextUI_TestRunner->doRun(Object(PHPUnit_Framework_TestSuite), Array)
#10 /var/www/phpdev/vendor/phpunit/phpunit/src/TextUI/Command.php(132): PHPUnit_TextUI_Command->run(Array, true)
#11 /var/www/phpdev/vendor/phpunit/phpunit/phpunit(55): PHPUnit_TextUI_Command::main()
#12 {main}.
FAILURES!
Tests: 1, Assertions: 1, Failures: 1.
Should I instead remove the type hint and use is_array($values) to tell whether the correct type is passed then throw an exception? In PHPUnit I am expecting an exception is thrown anyway. By the way, below is my test:
/**
* #expectedException InvalidArgumentException
*/
public function testCreateMethodWithInvalidArguments()
{
// pass invalid argument, should be an array of values
$result = $this->userTable->create('invalid argument type');
}
PHPUnit just has to be made aware that you are expecting and exception so it can properly handle it and report upon it.
public function testExceptionHasRightMessage()
{
$this->setExpectedException(
'InvalidArgumentException', 'Right Message'
);
throw new InvalidArgumentException('Some Message', 10);
}
This was pulled from the example 2.11 at PHP Unit Documentation - Writing Unit Tests