OOP PHP error for non-object when trying to get user info from database [duplicate] - pdo

This question already has answers here:
Call to a member function on a non-object [duplicate]
(8 answers)
Closed 10 years ago.
I'm trying to make oop class to get user info but i get this error
Fatal error: Call to a member function prepare() on a non-object in functions.php
user.php - >
include_once 'functions.php';
$user = new User();
echo $user->get_fullname(5);
functions.php ->
include_once 'database.php';
class User
{
public function connect()
{
$dbh = new DB_Class();
}
public function get_fullname($uid)
{
$getName = $dbh->prepare("SELECT EmailAddress FROM users WHERE UserID =:username");
$getName->bindParam(':username', $uid);
$getName->execute();
$rowName = $getName->fetch();
$email = $rowName['emailaddress'];
return $email;
}
}
database.php - >
class DB_Class
{
public function connect() {
try {
$dbh= new PDO("mysql:host=localhost;dbname=root",'users','password', array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"
));
} catch (PDOException $e) {
echo $e->getMessage();
}
$dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_WARNING);
$dbh->setAttribute(PDO::ATTR_CASE,PDO::CASE_LOWER);
}
}
What i'm doing wrong :(

You never actually give access to the PDO instance $dbh to the things youre trying to use it in. It seems like youre using classes simple as groupings of functions but also expecting some magic to happen :-) This is how i would do it with your existingcode:
class DB_Class {
protected $dsn;
protected $user;
protected $password;
protected $connection;
public function __construct($dsn = null, $user = null, $password = null)
{
$this->dsn = $dsn;
$this->user = $user;
$this->password = $password;
}
public function connect()
{
if($this->connection) {
return $this->connection;
}
try {
$this->connection = new PDO($this->dsn,$this->user, $this->password,
array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"
));
$this->connection->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_WARNING);
$this->connection->setAttribute(PDO::ATTR_CASE,PDO::CASE_LOWER);
return $this->connection;
}
catch (PDOException $e) {
return false;
}
}
}
class User {
protected $db;
public function __construct(DB_Class $db = null)
{
$this->db = $db;
}
public function setDb(DB_Class $db)
{
$this->db = $db;
}
public function get_fullname($uid)
{
$stmt = $this->db->connect()->prepare("SELECT EmailAddress FROM users WHERE UserID =:username");
$stmt->execute(array(':username', $uid));
if($row = $getName->fetch()) {
return $row['emailaddress'];
} else {
return null;
}
}
}

The $dbh variable isn't being passed into the get_fullname function. You'd need to do something like:
public function connect()
{
$dbh = new DB_Class();
return $dbh;
}
public function get_fullname($uid)
{
$dbh = $this->connect();

you need to declare $dbh as property of User class and access it via $this identifier:
class User
{
protected $dbh;
public function connect()
{
$this->dbh = new DB_Class();
}
public function get_fullname($uid)
{
$getName =$this->dbh->prepare("SELECT EmailAddress FROM users WHERE UserID =:username");
$getName->bindParam(':username', $uid);
$getName->execute();
$rowName = $getName->fetch();
$email = $rowMail['emailaddress'];
return $email;
}
}

You are never actually assigning your class properties as a property, all you are doing when declaring the variables inside of your methods is putting them into the methods current scope and they are destroyed once the method finishes execution.
To properly set a property within a class you need to declare them using $this->varname and the same goes for accessing them.
You are also using an incorrect name for the classes construction, the constructor must be set to __construct not connect.
As you can see in the updated code the $dbh variable is now a property of the User class and can be called between it's methods.
User Class
class User
{
public function __construct()
{
$this->dbh = new DB_Class();
}
public function get_fullname($uid)
{
$getName = $this->dbh->getConnection()->prepare("SELECT EmailAddress FROM users WHERE UserID =:username");
$getName->bindParam(':username', $uid);
$getName->execute();
$rowName = $getName->fetch();
$email = $rowName['emailaddress'];
return $email;
}
}
Database Class
class DB_Class
{
public function __construct() {
try {
$this->dbh = new PDO("mysql:host=localhost;dbname=root",'users','password', array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"
));
} catch (PDOException $e) {
echo $e->getMessage();
}
$this->dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_WARNING);
$this->dbh->setAttribute(PDO::ATTR_CASE,PDO::CASE_LOWER);
}
public function getConnection() {
return $this->dbh;
}
}
You will benefit greatly by using http://us2.php.net/manual/en/oop5.intro.php as a resource.

Related

How To Get data From Request Login Form Laravel

I have a problem, i need get data request from other field on login form to dashboard.
Login Form
enter image description here
My Login Controller, and i use default auth from laravel
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* #var string
*/
protected $redirectTo = '/home';
public function username(){
return 'username';
}
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest')->except('logout');
}
}
My AuthentictesUser
<?php
namespace Illuminate\Foundation\Auth;
use Illuminate\Http\Request;
use App\Tahun;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\ValidationException;
trait AuthenticatesUsers
{
use RedirectsUsers, ThrottlesLogins;
public function showLoginForm()
{
$tahuns = \DB::table('tahuns')->where('active','<>', '2')
->orderBy('id','desc')->get();
return view('auth.login', compact('tahuns'));
}
public function login(Request $request)
{
$this->validateLogin($request);
if ($this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
if ($this->attemptLogin($request)) {
return $this->sendLoginResponse($request);
}
$this->incrementLoginAttempts($request);
return $this->sendFailedLoginResponse($request);
}
protected function validateLogin(Request $request)
{
$this->validate($request, [
$this->username() => 'required|string',
'password' => 'required|string',
'tahun' => 'required|string',
]);
}
protected function attemptLogin(Request $request)
{
return $this->guard()->attempt(
$this->credentials($request), $request->filled('remember')
);
}
protected function credentials(Request $request)
{
return $request->only($this->username(), 'password');
}
protected function sendLoginResponse(Request $request)
{
$request->session()->regenerate();
$this->clearLoginAttempts($request);
return $this->authenticated($request, $this->guard()->user())
?: redirect()->intended($this->redirectPath());
}
protected function authenticated(Request $request, $user)
{
//
}
protected function sendFailedLoginResponse(Request $request)
{
throw ValidationException::withMessages([
$this->username() => [trans('auth.failed')],
]);
}
public function username()
{
return 'email';
}
public function logout(Request $request)
{
$this->guard()->logout();
$request->session()->invalidate();
return redirect('/');
}
protected function guard()
{
return Auth::guard();
}
}
How if i use data from fill tahun(year) on login form?
And i need send data from login form to my dashboard.
There is no need to replace the trait since you can simply override the trait methods in your LoginController, just like you did with username().
Override public function showLoginForm() and return your custom view.
Override protected function validateLogin(Request $request) to validate your new fields.
Finally, override protected function authenticated(Request $request, $user) and save the tahun data or return a redirect response.

Php class with statc function to connect to database

I have this class to connect to my database, but when I try to use it, always return null.
if I use these credentials in a single php file without class and static function, it works.
This is how I use it
<?php
include 'bdconexion.php';
$var ="hola";
$pdo=BaseDatos::Conectar();
print '<h3>PDO: simple select</h3>';
foreach($pdo->query( 'SELECT * FROM productos;' ) as $row)
{
echo $row['descripcion'];
}
Some help will be great
class BaseDatos
{
private static $bdname = 'bd';
private static $bdhost = 'localhost';
private static $user = 'root';
private static $pass = 'pass';
//private static $mssqldriver = '{SQL Server}';
//private static $mssqldriver = '{SQL Server Native Client 11.0}';
//private static $mssqldriver = '{ODBC Driver 11 for SQL Server}';
private static $conn = null;
public function __construct()
{
die('La funcion de inicio no es permitida');
}
public static function conectar()
{
if (null==self::$conn) {
try {
$conn = new PDO("mysql:host=".self::$bdhost.";dbname=".self::$bdname,self::$user,self::$pass);
} catch (PDOException $e) {
die($e->getMessage());
}
}
return self::$conn;
}
public static function desconectar()
{
self::$conn=null;
}
}

Yii2 Login from DB (Setting unknown property: app\models\User::password_hash)

I want the user authentication in Yii to be based on user table in my database. This is my User model:
<?php
namespace app\models;
use Yii;
use yii\base\NotSupportedException;
use yii\db\ActiveRecord;
use yii\helpers\Security;
use yii\web\IdentityInterface;
/**
* This is the model class for table "user".
*
* #property integer $id
* #property string $username
* #property string $password
* #property string $title
*/
class User extends \yii\db\ActiveRecord implements IdentityInterface
{
public static function tableName()
{
return 'user';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['username', 'password'], 'required'],
[['username', 'password'], 'string', 'max' => 100]
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'UserID',
'username' => 'Username',
'password' => 'Password',
];
}
public static function findIdentity($id) {
return static::findOne($id);
}
public static function findIdentityByAccessToken($token, $type = null) {
return static::findOne(['access_token' => $token]);
}
public static function findByUsername ($username){
return static::findOne(['username' => $username]);
}
public static function findbyPasswordResetToken($token)
{
$expire= \Yii::$app->params['user.passwordResetTokenExpire'];
$parts = explode('_', $token);
$timestamp = (int) end($parts);
if ($timestamp + $expire < time()) {
//token expired
return null;
}
return static::findOne(['password_reset_token' => $token ]);
}
public function getId() {
return $this->getPrimaryKey();
}
public function getAuthKey() {
return $this->auth_key;
}
public function validateAuthKey($authKey) {
return $this->getAuthKey() === $authKey;
}
public function validatePassword($password){
$this->password_hash= Yii::$app->security->generatePasswordHash ($password);
}
public function generateAuthKey()
{
$this->auth_key = Yii::$app->security->generateRandomKey();
}
/**
* Generates new password reset token
*/
public function generatePasswordResetToken()
{
$this->password_reset_token = Yii::$app->security->generateRandomKey() . '_' . time();
}
/**
* Removes password reset token
*/
public function removePasswordResetToken()
{
$this->password_reset_token = null;
}
}
But it is giving me this error when I try to login:
Setting unknown property: app\models\User::password_hash
This is actionLogin in siteController:
public function actionLogin()
{
if (!\Yii::$app->user->isGuest) {
return $this->goHome();
}
$model = new LoginForm();
if ($model->load(Yii::$app->request->post()) && $model->login()) {
return $this->goBack();
} else {
return $this->render('login', [
'model' => $model,
]);
}
}
And this is the code in LoginForm.php:
public function validatePassword($attribute, $params)
{
if (!$this->hasErrors()) {
$user = $this->getUser();
if (!$user || !$user->validatePassword($this->password)) {
$this->addError($attribute, 'Incorrect username or password.');
}
}
}
/**
* Logs in a user using the provided username and password.
* #return boolean whether the user is logged in successfully
*/
public function login()
{
if ($this->validate()) {
return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600*24*30 : 0);
} else {
return false;
}
}
I don't know what is wrong, could you please help me fix this?
This is because the column "password_hash" assigned in the function "validatePassword()" doesn't exist in database or is not declared in the User model.
If the password hash is stored in the database in "password" field, then change "validatePassword()" to,
public function validatePassword($password)
{
return $this->password === Yii::$app->security->generatePasswordHash ($password);
}
Here is the solution
1: Declare it in the user controller
* #property string $password_hash
class User extends ActiveRecord implements IdentityInterface
{
public $password;
/**
* #inheritdoc
*/
public static function tableName()
{
return '{{%user}}';
}
public function rules()
{
return [
[['username','email','first_name','last_name','address','password','contact_no','role'], 'safe'],
[['email'], 'unique'],
[['email'], 'email'],
];
}
.
.
....
public function validatePassword($password)
{
return Yii::$app->security->validatePassword($password, $this->password_hash);
}
2: In your LoginForm model rule function add this
['password', 'validatePassword'],
everything else looks okay. Hope this helps you

PHP - Using $this when not in object context

When I try to execute this code from inherited class I got this error Using $this when not in object context
here my code
abstract class Connection {
private static $host;
private static $username;
private static $password;
private static $database;
public function __construct() {
self::$host = 'localhost'; // database server address
self::$username = 'root'; //database server username;
self::$password = ''; //database server password;
self::$database = 'oms'; //database name
}
private function connect() {
return new PDO('mysql:host=' . Connection::$host . ';dbname=' . Connection::$database . '', Connection::$username, Connection::$password);
}
protected function execute($sql) {
$this->connect();
return $this->connect()->query($sql);
}
}
what are the reason for that? i don't use any static method in Connection class. SoWhy do give this error?
This is probably what you want:
abstract class Connection {
protected static $host;
protected static $username;
protected static $password;
protected static $database;
protected static $connection;
public static function load() {
self::$host = 'localhost'; // database server address
self::$username = 'root'; //database server username;
self::$password = ''; //database server password;
self::$database = 'oms'; //database name
}
protected static function connect() {
// Only create the connection once
if (!self::$connection) {
self::$connection = new PDO('mysql:host=' . self::$host . ';dbname=' . self::$database . '', self::$username, self::$password);
}
return self::$connection;
}
public static function execute($sql) {
return self::$connect()->query($sql);
}
}
// Because we can't use an abstract class
class ConcreteConnection extends Connection {}
// Execute a SQL call
ConcreteConnection::execute("SELECT * FROM `table`");
But then what you'll have is a Singleton Pattern which is a pain for testing and changing later. I'd recommend you make it like this:
abstract class Connection {
protected $host;
protected $username;
protected $password;
protected $database;
protected $connection;
public function _construct($host, $username, $password, $database) {
$this->host = $host;
$this->username = $username;
$this->password = $password;
$this->database = $database;
}
protected function connect() {
if (!$this->connection) {
$this->connection = new PDO('mysql:host=' . $this->host . ';dbname=' . $this->database . '', $this->username, $this->password);
}
return $this->connection;
}
public function execute($sql) {
return $this->connect()->query($sql);
}
}
// Because we can't use an abstract class
class ConcreteConnection extends Connection {}
// Inject our parameters into our class
$connection = new ConcreteConnection('host', 'username', 'password', 'database');
// Execute a SQL call
$connection->execute("SELECT * FROM `table`");

Creating dynamic attributes and properties in model class

I used code
$sql="SELECT 'Name' FROM XXX";
$names =$connection->createCommand($sql)->query()->readAll();
$myDynamicObject = new DynamicModel($names);
class DynamicModel extends CModel
{
protected $_members = array();
public function __construct($nameFields)
{
foreach ($nameFields as $member) {
$this->_members[$member] = null;
}
parent::__construct();
}
/**
* #return array validation rules for model attributes.
*/
public function rules()
{
$allMembers = implode(', ', array_keys($this->_members));
return array(
array($allMembers, 'required'),
);
}
public function __get($attribute)
{
if (in_array($attribute, array_keys($this->_members))) {
return $this->_members[$attribute];
} else {
return parent::__get($attribute);
}
}
public function __set($attribute, $value)
{
if (in_array($attribute, array_keys($this->_members))) {
return $this->_members[$attribute] = $value;
} else {
return parent::__set($attribute, $value);
}
}
public function getAttributes()
{
return $this->_members;
}
public function setAttributes($attributes)
{
$this->_members = $attributes;
}
}
i print this model in controller but
not nothing coming..server error came..
" More
An unexpected condition was encountered while the server was attempting to fulfill the request.
Error code: 500"
CModel is an abstract class and you need to at least implement the attributeNames() function.
In your case I guess the following should suffice:
public function attributeNames()
{
return array_keys($this->_members);
}