How to set up multiple PDO database connections in slim 4 and access them in a repository? - pdo

I tried to set up SLIM 4 with 2 PDO database connections.
I can't access the db nor db2 from a repository.
I guess I'm doing something wrong
I followed the slim 4 skeleton.
I created a db.php file in app for adding the db's definition in the container
I included db.php in index.php
I tried to access the db or db2 from a repository but it is not working
Here are my files :
app/db.php
declare(strict_types=1);
use PDO;
use DI\ContainerBuilder;
return function (ContainerBuilder $containerBuilder) {
// Global Settings Object
$containerBuilder->addDefinitions([
'db' => function (ContainerInterface $c) {
$settings = $c->get('settings');
$dbSettings = $settings['db'];
return new PDO('mysql:host=' . $dbSettings['host'] . ';dbname=' . $dbSettings['db'], $dbSettings['username'], $dbSettings['password'], $dbSettings['options']);
},
'db2' => function (ContainerInterface $c) {
$settings = $c->get('settings');
$dbSettings = $settings['db2'];
return new PDO('mysql:host=' . $dbSettings['host'] . ';dbname=' . $dbSettings['db'], $dbSettings['username'], $dbSettings['password'], $dbSettings['options']);
}
]);
};
public/index.php
declare(strict_types=1);
use App\Application\Handlers\HttpErrorHandler;
use App\Application\Handlers\ShutdownHandler;
use App\Application\ResponseEmitter\ResponseEmitter;
use DI\ContainerBuilder;
use Slim\Factory\AppFactory;
use Slim\Factory\ServerRequestCreatorFactory;
require __DIR__ . '/../vendor/autoload.php';
// Instantiate PHP-DI ContainerBuilder
$containerBuilder = new ContainerBuilder();
if (false) { // Should be set to true in production
$containerBuilder->enableCompilation(__DIR__ . '/../var/cache');
}
// Set up settings
$settings = require __DIR__ . '/../app/settings.php';
$settings($containerBuilder);
// Set up dependencies
$dependencies = require __DIR__ . '/../app/dependencies.php';
$dependencies($containerBuilder);
// Set up db, added by PF
$db = require __DIR__ . '/../app/db.php';
$db($containerBuilder);
// Set up repositories
$repositories = require __DIR__ . '/../app/repositories.php';
$repositories($containerBuilder);
// Build PHP-DI Container instance
$container = $containerBuilder->build();
// Instantiate the app
AppFactory::setContainer($container);
$app = AppFactory::create();
$callableResolver = $app->getCallableResolver();
// Register middleware
$middleware = require __DIR__ . '/../app/middleware.php';
$middleware($app);
// Register routes
$routes = require __DIR__ . '/../app/routes.php';
$routes($app);
/** #var bool $displayErrorDetails */
$displayErrorDetails = $container->get('settings')['displayErrorDetails'];
// Create Request object from globals
$serverRequestCreator = ServerRequestCreatorFactory::create();
$request = $serverRequestCreator->createServerRequestFromGlobals();
// Create Error Handler
$responseFactory = $app->getResponseFactory();
$errorHandler = new HttpErrorHandler($callableResolver, $responseFactory);
// Create Shutdown Handler
$shutdownHandler = new ShutdownHandler($request, $errorHandler, $displayErrorDetails);
register_shutdown_function($shutdownHandler);
// Add Routing Middleware
$app->addRoutingMiddleware();
// Add Error Middleware
$errorMiddleware = $app->addErrorMiddleware($displayErrorDetails, false, false);
$errorMiddleware->setDefaultErrorHandler($errorHandler);
// Run App & Emit Response
$response = $app->handle($request);
$responseEmitter = new ResponseEmitter();
$responseEmitter->emit($response);
src/Domain/ObContact/ObContactRepository.php
declare(strict_types=1);
namespace App\Domain\ObContact;
use PDO;
class ObContactRepository
{
/**
* #var PDO The database db
*/
private $db;
private $db2;
/**
* Constructor.
*
* #param PDO $db The database db
*/
public function __construct(PDO $db, PDO $db2)
{
$this->db = $db;
$this->db2 = $db2;
}
public function findByEmail(string $email)
{
if (empty($email))
return false;
return $this->db
->query('SELECT * FROM ob_contact WHERE email=:email')
->execute([':email' => $email])
->fetch();
}
}

Did you install PDO?
$ composer require faapz/pdo
Source:
https://github.com/FaaPz/PDO

Related

Symfony 4 - Problem sending email after change my DNS

Click here
to see my diagram app.
Hey, my client change her DNS (like that : xxx-dns.com to dns.com) and this is ok, except one problem.. In react native app, I have contact form for send message to pro "partner", and this pro partner are in the process of switching their emails from xxx-dns.com to dns.com.
BUT the contact form provide by SwitchMailer doesn't work with the new DNS, I have check all configuration files, same for the server, the controller is (I think) ok.
Please help me, it's been a week
I have var_dump() all information in my controller, check api endpoint, navigate into my server and check configuration files.
This is my contact controller :
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Twig\Environment as Twig;
class ContactController extends AbstractController
{
/**
* #var string
*/
private $mailFrom;
/**
* #var string
*/
private $backUrl;
private $tokenStorage;
public function __construct(string $mailFrom, string $backUrl, TokenStorageInterface $tokenStorage)
{
$this->mailFrom = $mailFrom;
$this->backUrl = $backUrl;
$this->tokenStorage = $tokenStorage;
}
/**
* #Route("/contact", name="app_send_contact")
*/
public function sendAction(\Swift_Mailer $mailer, Twig $twig, Request $request)
{
// Retrieve user
$currentUser = $this->tokenStorage->getToken()->getUser();
if (!$currentUser) {
return $this->json(array('success' => false, 'message' => 'Utilisateur introuvable.'));
}
// Prepare parameters
$contactObject = $request->request->get('object');
$contactMessage = $request->request->get('message');
// Retrieve establishment
$establishment = $currentUser->getEstablishments()->first();
if (!$establishment) {
return $this->json(array('success' => false, 'message' => 'Etablissement introuvable.'));
}
// Prepare mail
$mailTitle = $currentUser->getFirstname() . ' ' . $currentUser->getLastname() . ' vous a envoyé un message : ' . $contactObject;
// Send mail to establishment
$message = (new \Swift_Message($mailTitle))
->setFrom($this->mailFrom)
->setTo($establishment->getEmail())
->setReplyTo($currentUser->getEmail(), $currentUser->getFirstname() . ' ' . $currentUser->getLastname())
->setBody(
$twig->render(
'emails/contact.html.twig',
array(
'user' => $currentUser,
'establishment' => $establishment,
'contact_object' => $contactObject,
'contact_message' => $contactMessage,
'back_url' => $this->backUrl,
)
),
'text/html'
);
$mailer->send($message);
// Prepare mail
$mailTitle = 'Confirmation de demande de contact';
// Send mail to parent
$message = (new \Swift_Message($mailTitle))
->setFrom($this->mailFrom)
->setTo($currentUser->getEmail())
->setBody(
$twig->render(
'emails/contact_confirmation.html.twig',
array(
'user' => $currentUser,
'establishment' => $establishment,
'contact_object' => $contactObject,
'contact_message' => $contactMessage,
'back_url' => $this->backUrl,
)
),
'text/html'
);
$mailer->send($message);
return $this->json(array('success' => true));
}
}```

I don't know why this code is not creating google sheets

This is the code which is I am using to create a google sheet by using API. It is returning SpreadsheetId AND SpreadsheetUrl and other stuff also. But Not creating Sheet on my account.
Whenever I click on that SpreadsheetUrl which I recieved from API response it asks me for access. e.g. You DOn't Have access
require_once __DIR__ . '/vendor/autoload.php';
function getClient()
{
// TODO: Change placeholder below to generate authentication credentials. See
$client = new \Google_Client();
$client->setApplicationName('sheetCreate');
$client->setScopes([\Google_Service_Sheets::SPREADSHEETS]);
$client->setAccessType('offline');
$client->setAuthConfig(__DIR__ . '/credentials.json');
return $client;
}
//All Details
$client = getClient();
$service = new Google_Service_Sheets($client);
// TODO: Assign values to desired properties of `requestBody`:
//Sheet Title
$title="sheetCreate";
//Request Proporties
$requestBody = new Google_Service_Sheets_Spreadsheet([
'properties' => [
'title' => $title
]
]);
$response = $service->spreadsheets->create($requestBody);

PHP Slim Framework : Slim Application Error when using PDO

I want to use PDO with my Slim php application. When I use a simple select query and send json data to Twig page. But I keep getting this error : Slim Application Error
This is my code :
<?php
require __DIR__ . '/vendor/autoload.php';
$app = new Slim\App;
$container = $app->getContainer();
$container['view'] = function ($container) {
$templates = __DIR__ . '/templates/';
$cache = __DIR__ . '/tmp/views/';
$view = new Slim\Views\Twig($templates, array('cache' => false));
return $view;
};
$container['db'] = function ($container) {
$pdo = new PDO("mysql:host=localhost;DBName=dbsat", "root", "");
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
return $pdo;
};
$app->get('/', function ($request, $response) {
$sth = $this->db->prepare("SELECT * from client where id=:id");
$sth->bindParam("id", 1);
$sth->execute();
$todos = json_encode($sth->fetchAll());
$data = ['user' => $todos];
return $this->view->render($response, 'home.twig', $data);
});
$app->get('/login', function ($request, $response) {
return $this->view->render($response, 'login.twig');
});
$app->run();
?>
The problem appears at this line :
$sth = $this->db->prepare("SELECT * from client where id=:id");
Problem solved. It was caused by binding param
Message: Cannot pass parameter 2 by reference
By knowing the error I have fixed it. Thank you all.

My file not in uploads directory after upload was successful

I try to upload file using Yii2 file upload and the file path was successful saved to the database but the file was not saved to the directory I specify.. below is my code..
<?php
namespace backend\models;
use yii\base\Model;
use yii\web\UploadedFile;
use yii\Validators\FileValidator;
use Yii;
class UploadForm extends Model
{
/**
* #var UploadedFile
*/
public $image;
public $randomCharacter;
public function rules(){
return[
[['image'], 'file', 'skipOnEmpty' => false, 'extensions'=> 'png, jpg,jpeg'],
];
}
public function upload(){
$path = \Yii::getAlias("#backend/web/uploads/");
$randomString = "";
$length = 10;
$character = "QWERTYUIOPLKJHGFDSAZXCVBNMlkjhgfdsaqwertpoiuyzxcvbnm1098723456";
$randomString = substr(str_shuffle($character),0,$length);
$this->randomCharacter = $randomString;
if ($this->validate()){
$this->image->saveAs($path .$this->randomCharacter .'.'.$this->image->extension);
//$this->image->saveAs(\Yii::getAlias("#backend/web/uploads/{$randomString}.{$this->image->extension}"));
return true;
}else{
return false;
}
}
}
The controller to create the fileupload
namespace backend\controllers;
use Yii;
use backend\models\Product;
use backend\models\ProductSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use backend\models\UploadForm;
use yii\web\UploadedFile;
public function actionCreate()
{
$addd_at = time();
$model = new Product();
$upload = new UploadForm();
if($model->load(Yii::$app->request->post())){
//get instance of the uploaded file
$model->image = UploadedFile::getInstance($model, 'image');
$upload->upload();
$model->added_at = $addd_at;
$model->image = 'uploads/' .$upload->randomCharacter .'.'.$model->image->extension;
$model->save();
return $this->redirect(['view', 'product_id' => $model->product_id]);
} else{
return $this->render('create', [
'model' => $model,
]);
}
}
Does it throw any errors?
This is propably permission issue. Try changing the "uploads" directory permission to 777 (for test only).
You load your Product ($model) with form data.
if($model->load(Yii::$app->request->post()))
But Uploadform ($upload) never gets filled in your script. Consequently, $upload->image will be empty.
Since you declare 'skipOnEmpty' => false in the file validator of the UploadForm rules, the validation on $upload will fail.
That is why your if statement in the comments above (if($upload->upload()) doesn't save $model data.
I don't see why you would need another model to serve this purpose. It only complicates things, so I assume its because you copied it from a tutorial. To fix and make things more simple, just do the following things:
Add property to Product model
public $image;
Add image rule to Product model
[['image'], 'file', 'skipOnEmpty' => false, 'extensions'=> 'png, jpg,jpeg'],
Adjust controller create action
public function actionCreate()
{
$model = new Product();
if($model->load(Yii::$app->request->post()) && $model->validate()) {
// load image
$image = UploadedFile::getInstance($model, 'image');
// generate random filename
$rand = Yii::$app->security->generateRandomString(10);
// define upload path
$path = 'uploads/' . $rand . '.' . $image->extension;
// store image to server
$image->saveAs('#webroot/' . $path);
$model->added_at = time();
$model->image = $path;
if($model->save()) {
return $this->redirect(['view', 'product_id' => $model->product_id]);
}
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
Something like this should do the trick.
Your UploadForm class is already on Backend so on function upload of UploadForm Class it should be like this:
Change this line:
$path = \Yii::getAlias("#backend/web/uploads/");
to this:
$path = \Yii::getAlias("uploads")."/";

ZF2 - init or something that is called in every module controller

I have a Module called "Backend" and in this module I want to check for valid authentication on all pages except the backend_login page. How do I do this? I tried to add it to the onBootstrap in the Backend/Module.php , but it turns out that is called in my other modules as well... which is of course not what I want.
So how do I do this?
Thanks in advance!
To get clear information about zf2 authentication you can follow:
ZF2 authentication
adapter auth
database table auth
LDAP auth
digest auth....These all are different methods here is an example of database table auth:
in every controller's action, where you need user auth something should like this:
use Zend\Authentication\Result;
use Zend\Authentication\AuthenticationService;
use Zend\Authentication\Adapter\AdapterInterface;
use Zend\Db\Adapter\Adapter as DbAdapter;
use Zend\Authentication\Adapter\DbTable as AuthAdapter;
public function login($credential)
{
$bcrypt = new Bcrypt();
$user = new User();
$auth = new AuthenticationService();
$user->exchangeArray($credential);
$password = $user->password;
$data = $this->getUserTable()->selectUser($user->username);
if (!$data){
$message = 'Username or password is not correct!';
}
elseif($auth->getIdentity() == $user->username){
$message = 'You have already logged in';
}
elseif($bcrypt->verify($password, $data->password)){
$sm = $this->getServiceLocator();
$dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
$authAdapter = new AuthAdapter(
$dbAdapter,
'user',
'username',
'password'
);
$authAdapter -> setIdentity($user->username) -> setCredential($data->password);
$result = $auth->authenticate($authAdapter);
$message = "Login succesfull.Welcome ".$result->getIdentity();
} else {
$message = 'Username or password is not correct';
}
return new ViewModel(array("message" =>$message));
}
Like this in every action you can check whether it is authenticated or not
if($auth -> hasIdentity()){
//your stuff
}
else{
//redirected to your login route;
}
I had once a similar problem and figured it out within my Module.php in the onBootstrap() function. Try this, it worked for me:
class Module {
// white list to access with being non-authenticated
//the list may contain action names, controller names as well as route names
protected $whitelist = array('login');
//....
public function onBootstrap($e){
$app = $e->getApplication();
$em = $app->getEventManager();
$sm = $app->getServiceManager();
$list = $this->whitelist;
$auth = new AuthenticationService();
$em->attach(MvcEvent::EVENT_ROUTE, function($e) use ($list, $auth) {
$match = $e->getRouteMatch();
// No route match, this is a 404
if (!$match instanceof RouteMatch) {
return;
}
// Route is whitelisted
$action = $match->getParam('action');
if (in_array($action, $list) ) {
return;
}
// User is authenticated
if ($auth->hasIdentity()){
return;
}
// the user isn't authenticated
// redirect to the user login page, as an example
$router = $e->getRouter();
$url = $router->assemble(array(
'controller' => 'auth',
'action'=>'login'
), array(
'name' => 'route_name',
));
$response = $e->getResponse();
$response->getHeaders()->addHeaderLine('Location', $url);
$response->setStatusCode(302);
return $response;
}, -100);
}
}
Or you may see bjyauthorize.