I am using Silex PHP framework.
I have two files, the first is app.php:
<?php
require_once __DIR__.'/../vendor/autoload.php';
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\ParameterBag;
use Silex\ControllerProviderInterface;
$app = new Silex\Application();
$app['debug'] = true;
$app->register(new Silex\Provider\DoctrineServiceProvider(), array(
'db.options' => array(
'driver' => 'pdo_mysql',
'host' => 'localhost',
'dbname' => 'testapp',
'user' => 'root',
'password' => 'turoke55u',
),
));
$app->before(function (Request $request) {
if (0 === strpos($request->headers->get('Content-Type'), 'application/json')) {
$data = json_decode($request->getContent(), true);
$request->request->replace(is_array($data) ? $data : array());
}
});
$app->mount('/', include 'login.php');
$app->run();
And the second is login.php:
<?php
use Symfony\Component\HttpFoundation\Request;
$login = $app['controllers_factory'];
$login->post('/apiv1/user/login', function (Request $request) use ($login) {
$userinfo = array(
'email' => $request->request->get('email'),
'mode' => $request->request->get('mode'),
'password' => $request->request->get('password'),
);
$passwordcoding = sha1($userinfo['email']."66643asd");
$emailverification = "SELECT email,password FROM user WHERE email='".$userinfo['email']."'";
$selectemail = $login['db']->$fetchAll('SELECT * FROM user');
var_dump($emailverification);
});
return $login;
When I run the select on db I get this error:
Cannot use object of type Silex\ControllerCollection as array in /mnt/hgfs/Share_Folder/frontend/src/login.php on line 13
Does someone know a solution for that issue?
I have a second question, why if I change in app.php this:
$app->mount('/', include 'login.php');
To this:
$app->mount('/apiv1/user/login', include 'login.php');
And in login.php:
$login->post('/',
Like in the Silex documentation, the framework doesn't work?
You have a silly error in your function signature:
<?php
use Symfony\Component\HttpFoundation\Request;
$login = $app['controllers_factory'];
$login->post('/apiv1/user/login', function (Request $request) use ($login) {
// ^^^^^^^^
// this should be $app, not $login as this function is using the container
$userinfo = array(
'email' => $request->request->get('email'),
'mode' => $request->request->get('mode'),
'password' => $request->request->get('password'),
);
$passwordcoding = sha1($userinfo['email']."66643asd");
$emailverification = "SELECT email,password FROM user WHERE email='".$userinfo['email']."'";
// here you're using the $login as the container and it's a controller collection, so in the signature use the container not the $login
// vvvvvvvvvvvv
$selectemail = $login['db']->$fetchAll('SELECT * FROM user');
var_dump($emailverification);
});
return $login;
As for the second doubt you should elaborate more on "the framework doesn't work", explain the symptoms and the output (if error which error?)
Related
I work with MYSQL database in slim framework. Its perfectly worked.
But going to connect Postgresql, It not connected as well.
Here is the sample Coding: (settings.php)
declare(strict_types=1);
use App\Application\Settings\Settings;
use App\Application\Settings\SettingsInterface;
use DI\ContainerBuilder;
use Monolog\Logger;
return function (ContainerBuilder $containerBuilder) {
$containerBuilder->addDefinitions([
SettingsInterface::class => function () {
return new Settings([
'displayErrorDetails' => true, // Should be set to false in production
'logError' => true,
'logErrorDetails' => true,
'logger' => [
'name' => 'slim-app',
'path' => isset($_ENV['docker']) ? 'php://stdout' : __DIR__ . '/../logs/app.log',
'level' => Logger::DEBUG,
],
"db" =>
[
'driver' => 'pgsql',
'host' => 'localhost',
'port' => '5433',
'database' => 'test_db',
'username' => 'postgres',
'password' => 'password',
'prefix' => '',
'schema' => 'public',
]
]);
}
]);
};
Here is the code : (dependencies.php)
<?php
declare(strict_types=1);
use App\Application\Settings\SettingsInterface;
use DI\ContainerBuilder;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
use Monolog\Processor\UidProcessor;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
return function (ContainerBuilder $containerBuilder) {
$containerBuilder->addDefinitions([
LoggerInterface::class => function (ContainerInterface $c) {
$settings = $c->get(SettingsInterface::class);
$loggerSettings = $settings->get('logger');
$logger = new Logger($loggerSettings['name']);
$processor = new UidProcessor();
$logger->pushProcessor($processor);
$handler = new StreamHandler($loggerSettings['path'], $loggerSettings['level']);
$logger->pushHandler($handler);
return $logger;
},
PDO::class => function (ContainerInterface $c)
{
$settings = $c->get(SettingsInterface::class);
$dbSettings = $settings->get("db");
$host = $dbSettings['host'];
$dbname = $dbSettings['database'];
$username = $dbSettings['username'];
$password = $dbSettings['password'];
$port = $dbSettings['port'];
$dsn = new PDO ("pgsql:host=$host;port=$port;dbname=$dbname");
return new PDO($dsn, $username, $password);
},
]);
};
Here checking for database connection : (routes.php)
<?php
declare(strict_types=1);
use App\Application\Actions\User\ListUsersAction;
use App\Application\Actions\User\ViewUserAction;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\App;
use Slim\Interfaces\RouteCollectorProxyInterface as Group;
return function (App $app) {
$app->options('/{routes:.*}', function (Request $request, Response $response) {
// CORS Pre-Flight OPTIONS Request Handler
return $response;
});
$app->get('/', function (Request $request, Response $response) {
$response->getBody()->write('Hello world!');
return $response;
});
$app->group('/users', function (Group $group)
{
$group->get('', ListUsersAction::class);
$group->get('/{id}', ViewUserAction::class);
});
$app->post('/db-select', function (Request $request, Response $response)
{
$db = $this->get(PDO::class);
$sth = $db->prepare("SELECT * FROM login");
$sth->execute();
$data = $sth->fetchAll(PDO::FETCH_ASSOC);
$payload = json_encode($data);
$response->getBody()->write($payload);
return $response->withHeader('Content-Type', 'application/json');
});
};
If I run the command such as localhost:8000/db-select Its give me the following error:
{
"statusCode": 500,
"error": {
"type": "SERVER_ERROR",
"description": "SQLSTATE[08006] [7] fe_sendauth: no password supplied"
}
}
I worked the sample code for MYSQL it worked perfect.
What else missed for Postgresql connection?
Check extension for PostgreSQL is enabled
extension=pdo_pgsql
Also you may take help fromm this question
fe_sendauth: no password supplied error in postgresql + laravel
Here is a bug:
$dsn = new PDO ("pgsql:host=$host;port=$port;dbname=$dbname");
return new PDO($dsn, $username, $password);
Try this:
return new PDO("pgsql:host=$host;port=$port;dbname=$dbname", $username, $password);
I am having problems when trying the API that I made. When I tested it in Postman, it appeared false, even though my username and password were correct. Can you identify the problem with my code?
I really appreciate your help.
Auth_admin.php
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
require APPPATH . '/libraries/REST_Controller.php';
class Auth_admin extends REST_Controller
{
public function signin_post()
{
$this->load->model('model_admin', 'admin');
$params = array(
'username' => $this->post('username'),
'password' => md5($this->post('password'))
);
$result = $this->admin->admin_check($params);
if ($result){
if ($result->level == "admin"){
$response = array(
"status" => true,
"message" => "Authentication seccessfully",
"auth" => array(
"username" => $result->username
)
);
$this->set_response($response, REST_Controller::HTTP_OK);
}else{
$response = array(
"status" => false,
"message" => "This features does'nt exist for your Account"
);
$this->set_response($response, REST_Controller::HTTP_OK);
}
}
}
}
Model_admin.php
<?php
class Model_admin extends CI_Model
{
var $tablename;
public function __construct()
{
parent::__construct();
$this->tablename = "m_admin";
}
public function admin_check($data = array())
{
$params = array(
'username' => $data['username'],
'password' => $data['password'],
);
$this->db->where($params);
$query = $this->db->get($this->tablename);
return $query->row();
}
}
You have to pass function name after the controller name.
Like your path: http://192.168.122.1/project_name/auth_admin/signin it will work.
If that does not work, then please add index.php and check it because it depends on how you setup the project.
Having an issue using $this->container inside of my controllers.
When I try to access the logger/monolog in the code below, it fails miserably:
$this->container->get('logger')->addInfo('Request: users->get-one');
Here's the code in src/dependancies.php:
<?php
$container = $app->getContainer();
// monolog
$container['logger'] = function ($c) {
$logs = $c->get('settings')['logger'];
$logger = new Monolog\Logger($logs['name']);
$logger->pushProcessor(new Monolog\Processor\UidProcessor());
$logger->pushHandler(new Monolog\Handler\StreamHandler($logs['path'], $logs['level']));
return $logger;
};
// database
$container['db'] = function ($c) {
$database = $c->get('settings')['database'];
$capsule = new \Illuminate\Database\Capsule\Manager;
$capsule->addConnection([
'driver' => 'mysql',
'host' => $database['hostname'],
'database' => $database['database'],
'username' => $database['username'],
'password' => $database['password'],
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
]);
$capsule->setAsGlobal();
$capsule->bootEloquent();
return $capsule;
};
// register users controller
require __DIR__ . '/../src/controllers/users.php';
$container['UsersController'] = function($c) {
return new UsersController($c);
};
Below is the code that's in src/controllers/users.php:
<?php
use Psr\Container\ContainerInterface;
use Slim\Http\Request;
use Slim\Http\Response;
class UsersController {
protected $container;
public function __construct(ContainerInterface $container) {
$this->container = $container;
}
public function get(Request $request, Response $response, $args) {
$this->container->get('logger')->addInfo('Request: users->get-one');
/**
* TODO: Replace $args['id'] with the id from the current token payload
*/
$data = Users::find($args['id']);
return $response->withJSON($data)->withStatus(200);
}
public function create(Request $request, Response $response, $args) {
$this->logger->addInfo('Request: users->create');
$user = $request->getParsedBody();
$data = Users::create([
'first_name' => $user['first_name'],
'last_name' => $user['last_name'],
'email' => $user['email'],
'password' => password_hash($user['password'], PASSWORD_BCRYPT),
'telephone' => $user['telephone'],
'timezone' => $user['timezone'],
'verification' => '011010'
]);
return $response->withJSON($data)->withStatus(200);
}
public function update(Request $request, Response $response, $args) {
$this->logger->addInfo('Request: users->update');
$user = $request->getParsedBody();
$data = Users::where('id', $args['id'])->update([
'first_name' => $user['first_name'],
'last_name' => $user['last_name'],
'email' => $user['email'],
'password' => password_hash($user['password'], PASSWORD_BCRYPT),
'telephone' => $user['telephone'],
'timezone' => $user['timezone']
]);
return $response->withJSON($data)->withStatus(200);
}
public function delete(Request $request, Response $response, $args) {
$this->logger->addInfo('Request: users->delete');
$data = Users::destroy($args['id']);
return $response->withJSON($data)->withStatus(200);
}
/*
* ==============================
* Manager Functions Routines
* ==============================
*/
public function getAll(Request $request, Response $response, $args) {
$this->logger->addInfo('Request: admin->users->getAll');
$data = Users::all();
return $response->withJSON($data)->withStatus(200);
}
}
I have tried following different tutorials as well as the documentation on the Slim website however, nothing has seemed to fix the issue. I am sure it's something easily fixed that I am just missing.
PHP Slim 3 Framework - Use MonoLog in Custom Class - Using $this when not in object context - The accepted answer here just seems silly to do when I want to be able to access the entire app container and NOT just the logger.
Any help is appreciated.
Thank you!
Well, I figured it out. Apparently using two semicolons when invoking the controller routine is not the proper way of doing things. Oops!
/*
* users::read::one
* method:get
*/
$app->get('/users', '\UsersController::get');
When the code above is adjust to only use one semicolon, it works:
/*
* users::read::one
* method:get
*/
$app->get('/users', '\UsersController:get');
I do have trouble in setting password reset facility for custom user table (suppose 'customers' table). It was successful to generate a token for password reset but unable to do the reset because of Laravel considering its default table 'users', not the table I suppose to do reset. Changing default table users to customers in Config\Auth.php generate validation error
Passwords must be at least six characters and match the confirmation.
I just copy/pasting what I did so far
<?php
/*
Code Done by Arun
*/
namespace App\Http\Controllers\API\ResetPassword;
use App\Http\Controllers\API\Controller;
use Illuminate\Http\Request;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
use Illuminate\Foundation\Auth\ResetsPasswords;
use Illuminate\Support\Facades\Password;
use App\Model\Customer;
use Laravel\Passport\Client;
use Illuminate\Support\Facades\Auth;
class ResetPasswordController extends Controller
{
use ResetsPasswords;
public function __construct()
{
$this->middleware('api');
}
protected function guard()
{
return Auth::guard('api');
}
public function ResetPassword(Request $request)
{
$v = validator($request->only('email', 'token', 'password','confirm_password'), [
'token' => 'required|string|max:255',
'email' => 'required|string|email|max:255',
'password' => 'required|string',
'confirm_password' => 'required|string|min:6',
]);
if ($v->fails()) {
return response()->json(["error"=>$v->errors()->all()], 400);
}
else
{
$response = $this->broker()->reset(
$this->credentials($request), function ($user, $password) {
$this->resetPassword($user, $password);
});
}
return $response == Password::PASSWORD_RESET
? $this->sendResetResponse($response)
: $this->customResetFailedResponse($request, $response);
// $client = Client::where('password_client', 1)->first();
// $request->request->add([
// 'grant_type' => 'password',
// 'client_id' => $client->id,
// 'client_secret' => $client->secret,
// 'username' => $request->email,
// 'password' => $request->password,
// 'scope' => null,
// ]);
// // Fire off the internal request.
// $proxy = Request::create(
// 'oauth/token',
// 'POST'
// );
// return $response ;
}
}
Any Laravel expert can help me with the problem?
Im finally able to figure this out, im just posting answer may help others come across the same problem.
<?php
namespace App\Http\Controllers\API\Auth;
use App\Http\Controllers\API\Controller;
use Illuminate\Http\Request;
use Illuminate\Foundation\Auth\ResetsPasswords;
use Illuminate\Support\Facades\Password;
use App\Model\Customer;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Auth;
use GuzzleHttp\Client;
use DB;
class ResetPasswordController extends Controller
{
use ResetsPasswords;
protected $confirmEmail = false;
public function __construct()
{
}
public function resetPasswordCustomer(Request $request)
{
//Custome password reset mail has done in customer model
$v = validator($request->only('token', 'password','password_confirmation'), [
'token' => 'required|string|max:255',
'password' => 'required|string',
'password_confirmation' => 'required|string|min:6',
]);
if ($v->fails()) {
return response()->json(["error"=>$v->errors()->all()], 400);
}
else
{
$request->merge(['email'=> $this->checkTokenAgainstHashedValue($request->token)]);//Add new property to request..
$response = $this->broker()->reset(
$this->credentials($request), function ($user, $password) {
$this->resetPassword($user, $password);
});
}
return $response == Password::PASSWORD_RESET
? $this->authToken($request)
: $this->customResetFailedResponse($request, $response);
return $response ;
}
protected function checkTokenAgainstHashedValue($token)
{
$resetTable = DB::table('password_reset_customers')->select('token','email')->get();
foreach ($resetTable as $value) {
if (Hash::check($token, $value->token)) {
return $value->email;
}
}
return null;
}
protected function authToken(Request $request)
{
$http = new Client();
$response = $http->post('http://abcd.com/oauth/token', [
'form_params' => [
'grant_type' => 'password',
'client_id' => 2,
'client_secret' =>'qazrxGbDwrwbYXwbEbbkUFNO1zGB3eFYQN3AbG3m',
'username' => Auth::user()->email,
'password' => $request->password,
'scope' => '',
],
]);
return json_decode((string) $response->getBody(), true);
}
public function broker()
{
return Password::broker('customers');
}
}
I have a simple form which after submitting redirects to processAction inside AuthController and in this action I want to create a simple table bar.
EDITED:
Referring to Zend framerwork DB DDL update, I made a little modification in below code
AuthController.php
<?php
namespace Blog\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Zend\Debug\Debug;
use Blog\Form\LoginForm;
use Zend\Authentication\AuthenticationService;
use Zend\Db\Adapter\AdapterInterface;
use Zend\Db\Sql\Sql;
use Zend\Db\Sql\Ddl;
use Zend\Db\Sql\Ddl\Column;
use Zend\Db\Sql\Insert;
use Zend\Authentication\Adapter\DbTable as DbTableAuthAdapter;
class AuthController extends AbstractActionController
{
protected $adapter;
public function getAdapter()
{
if (!$this->adapter) {
$sm = $this->getServiceLocator();
$this->adapter = $sm->get('Zend\Db\Adapter\Adapter');
}
return $this->adapter;
}
public function indexAction()
{
return new ViewModel();
}
public function processAction()
{
$DB = new \Zend\Db\Adapter\Adapter(array(
'driver' => 'Pdo',
'database' => 'blog',
'username' => 'root',
'password' => 'mysql'
));
$this->adapter = $this->getAdapter();
$sql = new Sql($this->adapter);
$table = new Ddl\CreateTable('bar');
$table->addColumn(new Column\Integer('id'));
$table->addColumn(new Column\Varchar('name', 255));
$table->setTable('bar');
$results = $this->adapter->query($sql->getSqlStringForSqlObject($table), $this->adapter ::QUERY_MODE_EXECUTE);
return new ViewModel();
}
}
global.php:
return array(
'db' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=blog;host=localhost',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
),
'service_manager' => array(
'factories' => array(
'Zend\Db\Adapter\Adapter'
=> 'Zend\Db\Adapter\AdapterServiceFactory',
),
),
);
Module.php
<?php
namespace Blog;
use Zend\ModuleManager\Feature\AutoloaderProviderInterface;
use Zend\ModuleManager\Feature\ConfigProviderInterface;
class Module implements AutoloaderProviderInterface,ConfigProviderInterface
{
public function getAutoloaderConfig()
{
return array(
'Zend\Loader\StandardAutoloader' => array(
'namespaces' => array(
__NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
),
),
);
}
public function getConfig()
{
return include __DIR__ . '/config/module.config.php';
}
public function getServiceConfig()
{
return array(
'factories' =>array(
'Zend\Db\Adapter\Adapter' => function ($sm) {
$config = $sm->get('Config');
return new \Zend\Db\Adapter\Adapter($config['db']);
}
)
);
}
}
Problem:(Updated)
table bar is not created and shows error like
Fatal error: Class 'Blog\Controller\Zend\Db\Adapter\Adapter' not found
in /var/www/zend2/module/Blog/src/Blog/Controller/AuthController.php
on line 110
if I print
echo $sql->getSqlStringForSqlObject($table);
The query prints like this
CREATE TABLE `bar` ( `id` INTEGER NOT NULL, `name` VARCHAR(255) NOT NULL )
but table was not there.
Error occurs in below line of code as it is not able to identify adapter :
$results = $this->adapter->query($sql->getSqlStringForSqlObject($table), $this->adapter ::QUERY_MODE_EXECUTE);
But works in this way:
$results = $this->adapter->query($sql->getSqlStringForSqlObject($table), $DB ::QUERY_MODE_EXECUTE);
I am using Zend 2.4
I think you are trying to access non existing service. You can try to create a service factory:
config.php
<?php
return [
'db' => [
'driver' => 'Pdo',
'database' => 'blog',
'username' => 'root',
'password' => 'mysql'
]
];
Module.php
<?php
class Module
{
public function getServiceConfig()
{
return [
'factories' => [
'Zend\Db\Adapter\Adapter' => => function ($sm) {
$config = $sm->get('Config');
return new \Zend\Db\Adapter\Adapter($config['db']);
},
],
];
}
}
Then, you can access the service with the service manager:
AuthController.php
class AuthController extends AbstractActionController
{
public function getAdapter()
{
if (!$this->adapter) {
$sm = $this->getServiceLocator();
$this->adapter = $sm->get('Zend\Db\Adapter\Adapter');
}
return $this->adapter;
}
public function processAction()
{
$this->adapter = $this->getAdapter();
$sql = new Sql($this->adapter);
// other stuff here
}
}
You can find more examples here and here.
For beginners in ZF2 ,the query execute won't work if you don't instantiate class Zend\Db\Adapter\Adapter correctly.
I corrected like
$DB = new \Zend\Db\Adapter\Adapter(array(
'driver' => 'Pdo',
'database' => 'blog',
'username' => 'root',
'password' => 'mysql'
));
Also below line of code :
$results = $this->adapter->query($sql->getSqlStringForSqlObject($table), $DB ::QUERY_MODE_EXECUTE);
Ref Fatal error : class not found in Zend framework 2
Note: I still fail to understand why $this->adapter = $this->getAdapter(); not working instead of $DB.Any hint will be appreciated.