Project Structure
public/index.php
<?php
require __DIR__ . '/../vendor/autoload.php';
ini_set('display_errors', 'On');
if (PHP_SAPI == 'cli-server') {
// To help the built-in PHP dev server, check if the request was actually for
// something which should probably be served as a static file
$url = parse_url($_SERVER['REQUEST_URI']);
$file = __DIR__ . $url['path'];
if (is_file($file)) {
return false;
}
}
session_start();
// Instantiate the app
$settings = require __DIR__ . '/../src/settings.php';
$app = new \Slim\App($settings);
// Set up dependencies
require __DIR__ . '/../src/dependencies.php';
// Register middleware
require __DIR__ . '/../src/middleware.php';
// Register routes
require __DIR__ . '/../src/routes.php';
// Run app
$app->run();
Here we have the composer.json
{
"autoload":{
"psr-4": {
"App\\": "src"
}
},
"require": {
"php": ">=5.5.0",
"slim/slim": "^3.1",
"slim/php-view": "^2.0",
"monolog/monolog": "^1.17",
"illuminate/database": "~5.1",
"slim/twig-view": "^2.3"
},
"require-dev": {
"phpunit/phpunit": ">=4.8 < 6.0"
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
"config": {
"process-timeout" : 0
},
}
Here is my controller, i obtain a error with the namespace and in all the examples that i have seen use this so.. I don't know what to do more
<?php
namespace \App\Controllers;
class Homecontroller
{
protected $container;
// constructor receives container instance
public function __construct(ContainerInterface $container) {
$this->container = $container;
}
public function home($request, $response, $args) {
echo "locura";
// your code
// to access items in the container... $this->container->get('');
return $response;
}
public function contact($request, $response, $args) {
// your code
// to access items in the container... $this->container->get('');
return $response;
}
}
Actual configuration
In my routes.php I have put this:
$app->get('/new', \Homecontroller::class . ':home');
Before configuration
In the above code, I tried to create the controller into the container, and then use
$app->get('/new', '\HomeController:home');
And in the dependencies.php I put this code:
$container['HomeController'] = function($c) {
$view = $c->get("view"); // retrieve the 'view' from the container
return new HomeController($view);
};
but I didn't obtain any result with any configuration
I would like to load the HomeController from router
This is the error that I have when I put api.powertv/new
Type: RuntimeException
Message: Callable Homecontroller does not exist
File: /Users/alfonso/Sites/powertv_api/vendor/slim/slim/Slim/CallableResolver.php
Line: 90
i come here, and I put this post like my last resource, if this fails I don't know what I am going to do.
Try to use absolute namespace path in your:
dependencies.php
$container['yourController'] = function ($c) {
$view = $c['view'];
return new \App\Controllers\YourController($view);
}
routes.php
$app->get('your_defined_route_name', \App\Controllers\YourController::class . ':YourControllerMethod');
The name inside the container and thoose who you use in the route must match
You've been set the container key to HomeController and used \HomeController in the route, these strings are not equal.
either self create the strings
$container['HomeController'] = function($c) {
$view = $c->get("view"); // retrieve the 'view' from the container
return new HomeController($view);
};
$app->get('/new', 'HomeController:home');
or use the ::class syntax for both:
$container[HomeController::class] = function($c) {
$view = $c->get("view"); // retrieve the 'view' from the container
return new HomeController($view);
};
$app->get('/new', [HomeController::class, 'home');
// or $app->get('/new', HomeController::class . ':home');
with the answer of Pheara I obtain another error, is the next:
Type: Error
Message: Undefined constant 'App\controllers'
File:/Users/alfonso/Sites/powertv_api/src/Controllers/HomeController.php
Line: 5
the trace of the error is the next:
/Users/alfonso/Sites/powertv_api/vendor/composer/ClassLoader.php(444): include()
#1 /Users/alfonso/Sites/powertv_api/vendor/composer/ClassLoader.php(322): Composer\Autoload\includeFile('/Users/alfonso/...')
#2 [internal function]: Composer\Autoload\ClassLoader- >loadClass('App\\Controllers...')
#3 [internal function]: spl_autoload_call('App\\Controllers...')
#4 /Users/alfonso/Sites/powertv_api/vendor/slim/slim/Slim/CallableResolver.php(89): class_exists('App\\Controllers...')
#5 /Users/alfonso/Sites/powertv_api/vendor/slim/slim/Slim/CallableResolver.php(67): Slim\CallableResolver->resolveCallable('App\\Controllers...')
#6 /Users/alfonso/Sites/powertv_api/vendor/slim/slim/Slim/CallableResolverAwareTrait.php(45): Slim\CallableResolver->resolve('App\\Controllers...')
#7 /Users/alfonso/Sites/powertv_api/vendor/slim/slim/Slim/Route.php(330): Slim\Routable->resolveCallable('App\\Controllers...')
#8 /Users/alfonso/Sites/powertv_api/vendor/slim/slim/Slim/MiddlewareAwareTrait.php(117): Slim\Route->__invoke(Object(Slim\Http\Request), Object(Slim\Http\Response))
#9 /Users/alfonso/Sites/powertv_api/vendor/slim/slim/Slim/Route.php(313): Slim\Route->callMiddlewareStack(Object(Slim\Http\Request), Object(Slim\Http\Response))
#10 /Users/alfonso/Sites/powertv_api/vendor/slim/slim/Slim/App.php(495): Slim\Route->run(Object(Slim\Http\Request), Object(Slim\Http\Response))
#11 /Users/alfonso/Sites/powertv_api/vendor/slim/slim/Slim/MiddlewareAwareTrait.php(117): Slim\App->__invoke(Object(Slim\Http\Request), Object(Slim\Http\Response))
#12 /Users/alfonso/Sites/powertv_api/vendor/slim/slim/Slim/App.php(388): Slim\App->callMiddlewareStack(Object(Slim\Http\Request), Object(Slim\Http\Response))
#13 /Users/alfonso/Sites/powertv_api/vendor/slim/slim/Slim/App.php(296): Slim\App->process(Object(Slim\Http\Request), Object(Slim\Http\Response))
#14 /Users/alfonso/Sites/powertv_api/public/index.php(39): Slim\App->run()
#15 {main}
For solve this error you have to put the namespace in the 3 line:
<?php
namespace [yournamespace]
//rest of your controller
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\\": ""
}
},
I'm looking how I can set up host user and pass from env
this don't work - need string not function
host('51.38.98.87')
->stage('production')
->user( function(){return getenv('PRODUCTION_USER'); )
->pass( function(){return getenv('PRODUCTION_PASS'); )
->port(22)
in Symfony 4 I use env and don't want setup hosts in ~/.ssh/config
Update1 :
<?php
namespace Deployer;
use Symfony\Component\Dotenv\Dotenv;
require 'recipe/symfony.php';
require_once 'vendor/autoload.php';
$dotenv = new Dotenv();
$dotenv->load(__DIR__.'/.env');
then
dep deploy production
get
dep deploy production
[Error] Class 'Symfony\Component\Dotenv\Dotenv' not found
#0 phar:///usr/local/bin/dep/src/Deployer.php(325): require()
#1 [internal function]: Deployer\Deployer::Deployer\{closure}()
#2 phar:///usr/local/bin/dep/src/Deployer.php(326): call_user_func(Object(Closure))
#3 phar:///usr/local/bin/dep/bin/dep(119): Deployer\Deployer::run('6.3.0',
Update 2
composer.json has symfony/dotenv
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.0",
"symfony/browser-kit": "^4.0",
"symfony/css-selector": "^4.0",
"symfony/debug-pack": "*",
"symfony/dotenv": "^4.0",
"symfony/maker-bundle": "^1.0",
"symfony/phpunit-bridge": "^4.0",
"symfony/profiler-pack": "*",
"symfony/web-server-bundle": "^4.0"
},
but still
namespace Deployer;
use Symfony\Component\Dotenv\Dotenv;
require 'vendor/autoload.php';
require 'recipe/symfony.php';
$dotenv = new Dotenv();
$dotenv->load(__DIR__.'/.env');
give my
Class 'Symfony\Component\Dotenv\Dotenv' not found
#0 phar:///usr/local/bin/dep/src/Deployer.php(325): require()
#1 [internal function]: Deployer\Deployer::Deployer\{closure}()
#2 phar:///usr/local/bin/dep/src/Deployer.php(326): call_user_func(Object(Closure))
#3 phar:///usr/local/bin/dep/bin/dep(119): Deployer\Deployer::run('6.3.0', '/home/grek/Phps...')
#4 /usr/local/bin/dep(4): require('phar:///usr/loc...')
#5 {main}
UPDATE 3
I create test file : ./test.php
<?php
use Symfony\Component\Dotenv\Dotenv;
require 'vendor/autoload.php';
(new Dotenv())->load(__DIR__.'/.env');
php test.php
works fine.
Run from same location dep deploy:staging
give my
[Error] Class 'Symfony\Component\Dotenv\Dotenv' not found
#0 phar:///usr/local/bin/dep/src/Deployer.php(325): require()
my deploy.php file
<?php
namespace Deployer;
use Symfony\Component\Dotenv\Dotenv;
require 'vendor/autoload.php';
require 'recipe/symfony.php';
(new Dotenv())->load(__DIR__.'/.env');
Deployer is installed globaly
whereis dep
dep: /usr/local/bin/dep
Did you tried to enable symfony/dotenv in your deploy.php file?
require_once 'vendor/autoload.php';
$dotenv = new Dotenv();
$dotenv->load(__DIR__.'/.env');
You need first to install dotenv component:
composer require --dev symfony/dotenv
Remove the --dev option if you use it in an environment with only production dependencies.
I'm using .env files to generate settings files and the way I've got around this was to to add a property to the host that indicates the .env and template files:
# hosts.yml
hostname:
...
env_file: .env.stage
settings_template: somewhere/file.template
# file.template
...
'database' => '{{DB_NAME}}',
...
Load the credentials with a function:
# deploy.php
// Loading of .env files
// add Symfony's dotenv as a requirement: composer global require symfony/dotenv:"^3"
function loadenv() {
$env_file = get('env_file');
$environment = file_get_contents($env_file);
$dotenv = new \Symfony\Component\Dotenv\Dotenv();
$data = $dotenv->parse($environment);
return $data;
};
Finally, create a task that calls the loadenv() function, writes the credentials to a file and uploads it to the server:
task('upload:settings', function () {
if (askConfirmation('Are you sure to generate and upload the settings?')) {
//Get template
$template = get('settings_template');
//Import secrets
$secrets = loadenv();
//Prepare replacement variables
$iterator = new \RecursiveIteratorIterator(
new \RecursiveArrayIterator($secrets)
);
$replacements = [];
foreach ($iterator as $key => $value) {
$keys = [];
for ($i = $iterator->getDepth(); $i > 0; $i --) {
$keys[] = $iterator->getSubIterator($i - 1)->key();
}
$keys[] = $key;
$replacements['{{' . implode('.', $keys) . '}}'] = $value;
}
//Create settings from template
$settings = file_get_contents($template);
$settings = strtr($settings, $replacements);
$tmpFilename = 'settings.tmp';
file_put_contents($tmpFilename, $settings);
upload($tmpFilename, '{{release_path}}/somewhere', ['options'=> ['--inplace']]);
}
});
php7.0, Phalcon 3.2, MongoDB 3.2.14
I want to connect to MongoDB, but in Phalcon documentation only about connection via MongoClient() and working with it. I have php7.0 and MongoClient() is deprecated in it. How I can correctly use \MongoDB\Driver\Manager() with Phalcon?
In services.php I wrote this:
/**
* MongoDB connection
*/
$di->set( "mongo", function () {
$config = $this->getConfig();
$db_string = sprintf( 'mongodb://%s:%s/%s', $config->mongodb->host, $config->mongodb->port, $config->mongodb->database );
if( isset( $config->mongodb->user ) AND isset( $config->mongodb->password ) ) {
$db_string = sprintf( 'mongodb://%s:%s#%s:%s/%s',
$config->mongodb->user,
(string)$config->mongodb->password,
$config->mongodb->host,
(string)$config->mongodb->port,
$config->mongodb->database );
}
try {
return new \MongoDB\Driver\Manager( $db_string );
} catch (MongoConnectionException $e) {
die( 'Failed to connect to MongoDB '.$e->getMessage() );
}
},
true
);
It works. But in models there are errors. In app/models/User.php I wrote:
use Phalcon\Mvc\Collection;
class User extends Collection
{
public function initialize()
{
$this->setSource('users');
}
}
And in controller:
class IndexController extends ControllerBase
{
public function indexAction()
{
echo User::count();
}
}
In browser I have this:
Call to undefined method ::selectcollection()
#0 [internal function]: Phalcon\Mvc\Collection::_getGroupResultset(Array, Object(User), Object(MongoDB\Driver\Manager))
#1 /var/www/testing/app/controllers/IndexController.php(8): Phalcon\Mvc\Collection::count()
#2 [internal function]: IndexController->indexAction()
#3 [internal function]: Phalcon\Dispatcher->callActionMethod(Object(IndexController), 'indexAction', Array)
#4 [internal function]: Phalcon\Dispatcher->_dispatch()
#5 [internal function]: Phalcon\Dispatcher->dispatch()
#6 /var/www/testing/public/index.php(42): Phalcon\Mvc\Application->handle()
#7 {main}
How I can do it correclty? :) sorry for my English, I from Russia :)
My original question is here.
Use Incubator package: https://github.com/phalcon/incubator
See example of using here -
https://github.com/phalcon/incubator/tree/master/Library/Phalcon/Db/Adapter#mongodbclient
I am using slim framework and trying to implement slim token authentication as middleware, now whenever i go to
localhost/project/restrict
i get the message "Token Not Found" which seems to be working fine however when i try to pass the token in the authorization parameter as per the middleware documentation
locahost/project/restrict?authorization=usertokensecret
i always get the error Class 'app\Auth' not found and in my error trace the below,
0 /Applications/AMPPS/www/project/vendor/dyorg/slim-token-authentication/src/TokenAuthentication.php(66):
{closure}(Object(Slim\Http\Request),
Object(Slim\Middleware\TokenAuthentication))
1 [internal function]: Slim\Middleware\TokenAuthentication->__invoke(Object(Slim\Http\Request),
Object(Slim\Http\Response), Object(Slim\App))
2 /Applications/AMPPS/www/project/vendor/slim/slim/Slim/DeferredCallable.php(43):
call_user_func_array(Object(Slim\Middleware\TokenAuthentication),
Array)
3 [internal function]: Slim\DeferredCallable->__invoke(Object(Slim\Http\Request),
Object(Slim\Http\Response), Object(Slim\App))
4 /Applications/AMPPS/www/project/vendor/slim/slim/Slim/MiddlewareAwareTrait.php(73):
call_user_func(Object(Slim\DeferredCallable),
Object(Slim\Http\Request), Object(Slim\Http\Response),
Object(Slim\App))
5 /Applications/AMPPS/www/project/vendor/slim/slim/Slim/MiddlewareAwareTrait.php(122):
Slim\App->Slim{closure}(Object(Slim\Http\Request),
Object(Slim\Http\Response))
6 /Applications/AMPPS/www/project/vendor/slim/slim/Slim/App.php(370): Slim\App->callMiddlewareStack(Object(Slim\Http\Request),
Object(Slim\Http\Response))
7 /Applications/AMPPS/www/project/vendor/slim/slim/Slim/App.php(295): Slim\App->process(Object(Slim\Http\Request),
Object(Slim\Http\Response))
8 /Applications/AMPPS/www/project/index.php(81): Slim\App->run()
9 {main}
here the code i am using
<?php
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;
require_once './vendor/autoload.php';
$app = new \Slim\App;
use Slim\App;
use Slim\Middleware\TokenAuthentication;
$config = [
'settings' => [
'displayErrorDetails' => true
]
];
$app = new App($config);
$authenticator = function($request, TokenAuthentication $tokenAuth){
$token = $tokenAuth->findToken($request);
$auth = new \app\Auth();
$auth->getUserByToken($token);
};
/**
* Add token authentication middleware
*/
$app->add(new TokenAuthentication([
'path' => '/restrict',
'authenticator' => $authenticator
]));
/**
* Public route example
*/
$app->get('/', function($request, $response){
$output = ['msg' => 'It is a public area'];
$response->withJson($output, 200, JSON_PRETTY_PRINT);
});
/**
* Restrict route example
* Our token is "usertokensecret"
*/
$app->get('/restrict', function($request, $response){
$output = ['msg' => 'It\'s a restrict area. Token authentication works!'];
$response->withJson($output, 200, JSON_PRETTY_PRINT);
});
$app->run();
?>
The reason that \app\Auth cannot be found is because it doesn't exist in the current composer autoload path.
First move the app to the root folder, where core and the root vendor folders are.
Then add
"autoload": {
"classmap": [
"app"
]
}
to the root composer.json.
Last, run composer dump-autoload -o in the root folder.
After that, \app\Auth should be in the autoload path and everything should work as expected.
I have problem with autoloader not loading classes properly. I am not sure if I am doing it right... I am using slim framework.
My composer.json looks like this:
{
"require": {
"slim/slim": "^3.0",
"robmorgan/phinx": "^0.6.6",
"vlucas/phpdotenv": "^2.4",
"philo/laravel-blade": "3.*"
},
"autoload": {
"psr-4": {
"Cipo\\": ["app/"]
}
}
}
And my directory structure:
app/
Controllers/
Console/
AuthController.php
UsersController.php
HomeController.php
Core/
AbstractController.php
router.php
database/
public/
index.php
vendor/
views/
storage/
composer.json
My router.php looks like this:
$app->get("/", Cipo\Controllers\HomeController::class . ":index");
$app->get("/auth/login", Cipo\Controllers\Console\AuthController::class . ":getLogin");
The problem is that / works and shows the proper HTML, but /auth/login does not work. Here is the error that is thrown:
[Tue Jan 31 14:11:37.758803 2017] [:error] [pid 1336] [client 44.44.44.1:54453] Slim Application Error:
Type: RuntimeException
Message: Callable Cipo\\Controllers\\Console\\AuthController does not exist
File: /var/www/cipo.me/vendor/slim/slim/Slim/CallableResolver.php
Line: 62
Trace: #0 /var/www/cipo.me/vendor/slim/slim/Slim/CallableResolverAwareTrait.php(45): Slim\\CallableResolver->resolve('Cipo\\\\Controller...')
#1 /var/www/cipo.me/vendor/slim/slim/Slim/Route.php(333): Slim\\Routable->resolveCallable('Cipo\\\\Controller...')
#2 /var/www/cipo.me/vendor/slim/slim/Slim/MiddlewareAwareTrait.php(116): Slim\\Route->__invoke(Object(Slim\\Http\\Request), Object(Slim\\Http\\Response))
#3 /var/www/cipo.me/vendor/slim/slim/Slim/Route.php(316): Slim\\Route->callMiddlewareStack(Object(Slim\\Http\\Request), Object(Slim\\Http\\Response))
#4 /var/www/cipo.me/vendor/slim/slim/Slim/App.php(438): Slim\\Route->run(Object(Slim\\Http\\Request), Object(Slim\\Http\\Response))
#5 /var/www/cipo.me/vendor/slim/slim/Slim/MiddlewareAwareTrait.php(116): Slim\\App->__invoke(Object(Slim\\Http\\Request), Object(Slim\\Http\\Response))
#6 /var/www/cipo.me/vendor/slim/slim/Slim/App.php(332): Slim\\App->callMiddlewareStack(Object(Slim\\Http\\Request), Object(Slim\\Http\\Response))
#7 /var/www/cipo.me/vendor/slim/slim/Slim/App.php(293): Slim\\App->process(Object(Slim\\Http\\Request), Object(Slim\\Http\\Response))
#8 /var/www/cipo.me/public/index.php(45): Slim\\App->run()
#9 {main}
View in rendered output by enabling the "displayErrorDetails" setting.
And AuthController.php snippet:
<?php
namespace Cipo\Controllers\Console;
use PDO;
use Cipo\Core\AbstractController;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Interop\Container\ContainerInterface;
/**
* Class AuthController
* #property \PDO db
* #property \Philo\Blade\Blade blade
*/
class AuthController extends AbstractController
{
// ...
public function getLogin(RequestInterface $request, ResponseInterface $response)
{
$response->getBody()->write($this->blade->view()->make("auth.login")->render());
return $response;
}
}