I have been attempting to make a login system with php oop however I have come across this error Warning: Illegal offset type....classes\Session.php on line 11 I'm not quite sure where I'm going wrong any advice would be appreciated.
login
if(Input::exists()){
if(Token::check(Input::get('token'))){
$validate = new Validate();
$validation = $validate->check($_POST, array(
'username' => array('required' => true),
'password' => array('required' => true)
));
if ($validation->passed()){
//log user in
$user = new User();
$login = $user->login(Input::get('username'), Input::get('password'));
if($login){
echo 'Success';
}else{
echo'<p>Sorry invalid details</p>';
}
} else{
foreach($validation->errors() as $error)
echo $error, '<br />';
}
}
}
?>
<form action="" method="POST">
<div class="field">
<label for="username" id="username"> Username </label>
<input type="text" name="username" id="username" autocomplete="off">
</div>
<div class="field">
<label for="password" id="password"> Password </label>
<input type="password" name="password" id="password" autocomplete="off">
</div>
<input type="hidden" name="token" value="<?php echo Token::generate();?>">
<input type="submit" value="Login">
</form>
User
<?php
class User{
private $_db,
$_data,
$_sessionName;
public function __construct($user = null){
$this ->_db = DB::getInstance();
$this->_sessionName = Config::get('session/session_name');
}
public function create($fields = array()){
if($this->_db->insert('users', $fields)){
throw new Exception('There was a problem creating account');
}
}
public function find($user = null){
if($user){
$field = (is_numeric($user)) ? 'id' : 'username';
$data = $this->_db->get('users', array($field, '=', $user));
if($data->count()) {
$this->_data = $data->first();
return true;
}
}
return false;
}
public function login($username = null, $password = null){
$user = $this->find($username);
if($user){
if($this->data()->password ===Hash::make($password, $this->data()->salt)){
Session::put($this->_sessionName, $this-data()->id);
return true;
}
}
return false;
}
private function data(){
return $this->_data;
}
}
Session
<?php
class Session {
public static function exists($name){
return(isset($_SESSION[$name])) ? true : false;
}
public static function put($name, $value){
return $_SESSION[$name] = $value;
}
public static function get($name){
return $_SESSION[$name];
}
public static function delete($name){
if(self::exists($name)){
unset($_SESSION[$name]);
}
}
public static function flash($name, $string =''){
if(self::exists($name)){
$session = self::get($name);
self::delete($name);
return $session;
} else {
self::put($name, $string);
}
}
}
index
<?php
require_once 'core/init.php';
if(Session::exists('home')){
echo '<p>' . Session::flash('home', 'You have been registered and can now log in!') . '</p>';
}
echo Session::get(Config::get('session/session_name'));
?>
You should check if session key exist before trying to access it:
<?php
class Session {
public static function put($name, $value){
return $_SESSION[$name] = $value;
}
public static function get($name)
{
return self::exists($name) ? $_SESSION[$name] : null;
}
public static function exists($name)
{
return #$_SESSION[$name] !== null;
}
public static function delete($name){
if(self::exists($name)){
unset($_SESSION[$name]);
}
}
public static function flash($name, $string =''){
if(self::exists($name)){
$session = self::get($name);
self::delete($name);
return $session;
} else {
self::put($name, $string);
}
}
}
Related
It doesn't update the data it keeps giving me an error. If the email already exist, it should tell me email exist but it can not update user data.
It give me this error:
Warning: PDOStatement::execute(): SQLSTATE[HY093]: Invalid parameter number: no parameters were bound in C:\xampp\htdocs\php.dev\classes\Model.php on line 37
classed/Model.php
abstract class Model {
protected $dbh;
protected $stmt;
public function __construct() {
$this->dbh = new PDO("mysql:host=".DB_HOST.";dbname=".DB_NAME, DB_USER, DB_PASS);
}
public function query($query) {
$this->stmt = $this->dbh->prepare($query);
}
// binds the prepare statement
public function bind($param, $value, $type = null) {
if (is_null($type)) {
switch (true) {
case is_int($value):
$type = PDO::PARAM_INT;
break;
case is_bool($value):
$type = PDO::PARAM_BOOL;
break;
case is_null($value):
$type = PDO::PARAM_NULL;
break;
default:
$type = PDO::PARAM_STR;
}
}
$this->stmt->bindValue($param, $value, $type);
}
public function execute() {
$this->stmt->execute();
}
public function resultSet() {
$this->execute();
return $this->stmt->fetchAll(PDO::FETCH_ASSOC);
}
public function lastInsertId() {
return $this->dbh->lastInsertId();
}
public function single(){
$this->execute();
return $this->stmt->fetch(PDO::FETCH_ASSOC);
}
public function emailExist() {
$this->execute();
return $this->stmt->fetch(PDO::FETCH_ASSOC);
}
}
controllers/users.php
class Users extends Controller{
protected function profile(){
if (!isset($_SESSION['is_logged_in'])) {//if user do not login they can not profile page
header('Location: '.ROOT_URL.'shares');
}
$viewmodel = new UserModel();
$this->returnView($viewmodel->profile(), true);
}
protected function register(){
if (isset($_SESSION['is_logged_in'])) {//if user do not logout they can not access register page
header('Location: '.ROOT_URL.'shares');
}
$viewmodel = new UserModel();
$this->returnView($viewmodel->register(), true);
}
protected function login(){
if (isset($_SESSION['is_logged_in'])) {//if user do not logout they can not access login page
header('Location: '.ROOT_URL.'shares');
}
$viewmodel = new UserModel();
$this->returnView($viewmodel->login(), true);
}
protected function logout(){
unset($_SESSION['is_logged_in']);
unset($_SESSION['user_data']);
session_destroy();
// Redirect
header('Location: '.ROOT_URL);
}
}
models/user.php
class UserModel extends Model {
public function profile() {
// Sanitize POST
$post = filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING);
if($post['updateProfile']) {
#$name = $post['name'];
#$email = $post['email'];
#$id = $post['id'];
if (empty($post['name']) || empty($post['email'])) {
Messages::setMsg('Please Fill All Form Fields', 'error');
return;
}
// check if email is already taken
$this->query('SELECT * FROM users WHERE email = :email');
$this->bind(':email', $post['email']);
$row = $this->emailExist();
if ($row) {
Messages::setMsg('Email already Exist', 'error');
return;
} else {
# Update the MySQL
$this->query("UPDATE users SET name =:name, email =:email WHERE id =:id");
$this->execute();
// Verify
if($this->lastInsertId()){
Messages::setMsg('Successfull Updated', 'success');
return;
} else {
Messages::setMsg('Error while updating data', 'error');
return;
}
}
}
return;
}
}
view/users/profile.php
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Update Data</h3>
</div>
<div class="panel-body">
<form method="post" action="<?php $_SERVER['PHP_SELF']; ?>">
<div class="form-group">
<label>Name</label>
<input type="text" name="name" class="form-control" value="<?php echo $_SESSION['user_data']['name'];?>" />
</div>
<div class="form-group">
<label>Email</label>
<input type="text" name="email" class="form-control" value="<?php echo $_SESSION['user_data']['email'];?>" />
<input type="hidden" name="id" class="form-control" value="" />
</div>
<input class="btn btn-primary" name="updateProfile" type="submit" value="Submit" />
</form>
</div>
</div>
Your class function execute() needs to accept array values for the bound parameters in your sql string.
In classed/Model.php change:
public function execute() {
$this->stmt->execute();
}
To:
public function execute($params=NULL) {
$this->stmt->execute($params);
}
You are not binding variables to the specified variable names in your sql string.
models/user.php - Replace:
$this->execute();
With:
$this->execute(array(':name' => $post['name'], ':email' => $post['email'], ':id'=>$post['id']));
I have the cookie set and can see it in the console. When I close the browser and re-open it, it shows the cookie is there still , but not the session. So I am trying to see why my code is not keeping the user logged in. I will provide all the files necessary below.
EDIT: I should elaborate on this a little. So when the user close's his/her browser the session should no longer be there, but the cookie should and it is. So once that happens I want to say okay since there is a cookie we will grab that user's cookie look it up in the db and retrieve their id. Then using that id from a sessions table look up the id from the users table and log that user in.
login.php:
<?php
require_once 'core/init.php';
if(Input::exists()) {
if(Token::check(Input::get('token'))) {
$validate = new Validate();
$validation = $validate->check($_POST,array(
'username' => array('required' => true),
'password' => array('required' => true)
));
if($validation->passed()) {
$user = new User();
$remember = (Input::get('remember') === 'on') ? true : false;
$login = $user->login(Input::get('username'), Input::get('password'), $remember);
if($login) {
Redirect::to('index.php');
} else {
echo '<p>Sorry, logging in failed</p>';
}
} else {
foreach($validation->errors() as $error) {
echo $error, '<br>';
}
}
}
}
?>
<form action="" method="post">
<div class="field">
<label for="username">Username</label>
<input type="text" name="username" id="username" autocomplete="off">
</div>
<div class="field">
<label for="password">Password</label>
<input type="password" name="password" id="password" autocomplete="off">
</div>
<div class="field">
<label for="remember">
<input type="checkbox" name="remember" id="remember">Remember Me
</label>
</div>
<input type="hidden" name="token" value="<?php echo Token::generate(); ?>">
<input type="submit" value="Log In">
</form>
init.php:
<?php
session_start();
$GLOBALS['config'] = array(
'mysql' => array(
'host' => '127.0.0.1',
'username' => 'root',
'password' => 'root',
'db' => 'register_login'
),
'remember' => array(
'cookie_name' => 'hash',
'cookie_expiry' => 604800
),
'session' => array(
'session_name' => 'user',
'token_name' => 'token'
)
);
spl_autoload_register(function($class) {
require_once 'classes/' . $class . '.php';
});
require_once 'functions/sanitize.php';
if(Cookie::exists(Config::get('remember/cookie_name')) && !Session::exists(Config::get('session/session_name'))) {
$hash = Cookie::get(Config::get('remember/cookie_name'));
$hashCheck = DB::getInstance()->get('users_session', array('hash', '=', $hash));
if($hashCheck->count()) {
$user = new User($hashCheck->first()->user_id);
$user->login();
}
}
?>
User.php: In this file under the public function login I put echo 'ok', and echo 'not ok' to see if my if was passing and I am getting 'no ok', so the if is not passing true. So my best guess is that $this->exists() is passing false. It should not be passing false though.
<?php
class User {
private $_db,
$_data,
$_sessionName,
$_cookieName,
$_isLoggedIn;
public function __construct($user = null){
$this->_db = DB::getInstance();
$this->_sessionName = Config::get('session/session_name');
$this->_cookieName = Config::get('remember/cookie_name');
if(!$user){
if(Session::exists($this->_sessionName)) {
$user = Session::get($this->_sessionName);
if($this->find($user)) {
$this->_isLoggedIn = true;
} else {
}
} else {
$this->find($user);
}
}
}
public function create($table,$fields = array()){
if(!$this->_db->insert($table, $fields)){
throw new Exception('There was a problem creating an account.');
}
}
public function find($user = null) {
if($user){
$field = (is_numeric($user)) ? 'id' : 'username';
$data = $this->_db->get('users', array($field, '=', $user));
if($data->count()) {
$this->_data = $data->first();
return true;
}
}
return false;
}
public function login($username = null, $password = null, $remember = false) {
if(!$username && !$password && $this->exists()) {
echo 'Ok';
//Session::put($this->_sessionName, $this->data()->id);
} else {
echo 'no ok';
$user = $this->find($username);
if($user){
if($this->data()->password === Hash::make($password, $this->data()->salt)) {
Session::put($this->_sessionName, $this->data()->id);
if($remember){
$hash = Hash::unique();
$hashCheck = $this->_db->get('users_session', array('user_id', '=', $this->data()->id));
if(!$hashCheck->count()) {
$this->_db->insert('users_session',array(
'user_id' => $this->data()->id,
'hash' => $hash
));
} else {
$hash = $hashCheck->first()->hash;
}
Cookie::put($this->_cookieName, $hash, Config::get('remember/cookie_expiry'));
}
return true;
}
}
}
return false;
}
public function exists() {
return (!empty($this->_data)) ? true: false;
}
public function data(){
return $this->_data;
}
public function isLoggedIn(){
return $this->_isLoggedIn;
}
public function logout(){
$this->_db->delete('users_session', array('user_id' ,'=' , $this->data()->id));
Session::delete($this->_sessionName);
Cookie::delete($this->_cookieName);
}
}
Session.php:
<?php
class Session {
public static function exists($name) {
return(isset($_SESSION[$name])) ? true : false;
}
public static function put($name, $value) {
return $_SESSION[$name] = $value;
}
public static function get($name) {
return $_SESSION[$name];
}
public static function delete($name) {
if(self::exists($name)) {
unset($_SESSION[$name]);
}
}
public static function flash($name, $string = '') {
if(self::exists($name)){
$session = self::get($name);
self::delete($name);
return $session;
} else {
self::put($name, $string);
}
}
}
I'm still following the login/register tutorial I have went over the videos a few times to see if maybe I made a typing mistake somewhere but I can't seem to find anything the error I'm getting is "Notice: Trying to get property of non-object"
I did look around it was suggested to try the below solution however it didn't work:
echo $user[0]->data()->username;
I know it has something to do with my data class, well I think it's my data class that's wrong.
index.php
<?php
require_once 'core/init.php';
if(Session::exists('home')){
echo '<p>' . Session::flash('home', 'You have been registered and can now log in!') . '</p>';
}
$user = new User();
echo $user->data()->username;
?>
Login
User.php
<?php
class User{
private $_db,
$_data,
$_sessionName;
public function __construct($user = null){
$this ->_db = DB::getInstance();
$this->_sessionName = Config::get('session/session_name');
if(!$user){
if(Session::exists($this->_sessionName)){
$user = Session::get($this->_sessionName);
if($this->find($user)){
$this->_isLoggedIn = true;
}else{
//logout
}
}
} else{
$this->find($user);
}
}
public function create($fields = array()){
if($this->_db->insert('users', $fields)){
throw new Exception('There was a problem creating account');
}
}
public function find($user = null){
if($user){
$field = (is_numeric($user)) ? 'id' : 'username';
$data = $this->_db->get('users', array($field, '=', $user));
if($data->count()) {
$this->_data = $data->first();
return true;
}
}
return false;
}
public function login($username = null, $password = null){
$user = $this->find($username);
if($user){
if($this->data()->password ===Hash::make($password, $this->data()->salt)){
Session::put($this->_sessionName, $this->data()->id);
return true;
}
}
return false;
}
public function data(){
return $this->_data;
}
}
Login.php
<?php
require_once 'core/init.php';
if(Input::exists()){
if(Token::check(Input::get('token'))){
$validate = new Validate();
$validation = $validate->check($_POST, array(
'username' => array('required' => true),
'password' => array('required' => true)
));
if ($validation->passed()){
//log user in
$user = new User();
$login = $user->login(Input::get('username'), Input::get('password'));
if($login){
echo 'Success';
}else{
echo'<p>Sorry invalid details</p>';
}
} else{
foreach($validation->errors() as $error)
echo $error, '<br />';
}
}
}
?>
<form action="" method="POST">
<div class="field">
<label for="username" id="username"> Username </label>
<input type="text" name="username" id="username" autocomplete="off">
</div>
<div class="field">
<label for="password" id="password"> Password </label>
<input type="password" name="password" id="password" autocomplete="off">
</div>
<input type="hidden" name="token" value="<?php echo Token::generate();?>">
<input type="submit" value="Login">
</form>
Home
Session.php
<?php
class Session {
public static function put($name, $value){
return #$_SESSION[$name] = $value;
}
public static function get($name)
{
return self::exists($name) ? #$_SESSION[$name] : null;
}
public static function exists($name)
{
return #$_SESSION[$name] !== null;
}
public static function delete($name){
if(self::exists($name)){
unset($_SESSION[$name]);
}
}
public static function flash($name, $string =''){
if(self::exists($name)){
$session = self::get($name);
self::delete($name);
return $session;
} else {
self::put($name, $string);
}
}
}
I'm assuming this is the offending code:
$user = new User();
echo $user->data()->username;
This code instantiates a User object, and we can see that the constructor expects the username (or possibly id?) to be given. If no username is given it looks like the find function simply returns false and hence the data array will be empty. This is why you get the error message.
Try calling the constructor with the current username, e.g.
$user = new User('test');
If it's possible for the index page to be loaded without a username, then you just need to add an additional check on the data object before you try to use it, e.g.
if (#$user->data())
echo $user->data()->username;
else
echo "Not logged in";
Basic typing mistake in my init.php file, I really hate myself...
When I login with the correct information I get the following message:
Notice: Undefined property: stdClass::$id in /var/www/classes/User.php on line 37
Success Login!
Line 37 in User.php is following
Session::put($this->_sessionName, $this->data()->id);
Also after i sign in and update page and go to /index.php just to try print out the session, I get nothing.
Following command on index.php page
echo Session::get(Config::get('session/session_name'));
If i don't sign in and just go to index.php i get the following message
Notice: Undefined index: user in /var/www/classes/Session.php on line 12
Login.php
<?php
require_once 'core/init.php';
ini_set('display_errors', 1);
error_reporting(~0);
if(Input::exists()) {
if(Token::check(Input::get('token'))) {
$validate = new Validate();
$validation = $validate->check($_POST, array(
'username' => array('required' => true),
'password' => array('required' => true)
));
if($validation->passed()) {
$user = new User();
$login = $user->login(Input::get('username'), Input::get('password'));
if($login) {
echo 'Success Login!';
} else {
echo 'Login failed';
}
} else {
foreach($validation->errors() as $error) {
echo $error;
}
}
}
}
?>
<form action="" method="post">
<div class="field">
<label for="username">Username</label>
<input type="text" name="username" id="username">
</div>
<div class="field">
<label for="password">Password</label>
<input type="password" name="password" id="password">
</div>
<input type="hidden" name="token" value="<?php echo Token::generate(); ?>">
<input type="submit" value="Logga in">
</form>
Session.php
<?php
class Session {
public static function exists($name) {
return (isset($_SESSION[$name])) ? true : false;
}
public static function put($name, $value) {
return $_SESSION[$name] = $value;
}
public static function get($name) {
return $_SESSION[$name];
}
public static function delete($name) {
if(self::exists($name)) {
unset($_SESSION[$name]);
}
}
public static function flash($name, $string = '') {
if(self::exists($name)) {
$session = self::get($name);
self::delete($name);
return $session;
} else {
self::put($name, $string);
}
}
}
User.php
<?php
class User {
private $_db,
$_data,
$_sessionName;
public function __construct($user = null) {
$this->_db = DB::getInstance();
$this->_sessionName = Config::get('session/session_name');
}
public function create($fields = array()) {
if(!$this->_db->insert('users', $fields)) {
throw new Exception('Could not create account');
}
}
public function find($user = null) {
if($user) {
$field = (is_numeric($user)) ? 'id' : 'username';
$data = $this->_db->get('users', array($field, '=', $user));
if($data->count()) {
$this->_data = $data->first();
return true;
}
}
return false;
}
public function login($username = null, $password = null) {
$user = $this->find($username);
if($user) {
if($this->data()->password === Hash::make($password, $this->data()->salt)) {
Session::put($this->_sessionName, $this->data()->id);
return true;
}
}
return false;
}
private function data() {
return $this->_data;
}
}
Token.php
<?php
class Token {
public static function generate() {
return Session::put(Config::get('session/token_name'), sha1(uniqid()));
}
public static function check($token) {
$tokenName = Config::get('session/token_name');
if(Session::exists($tokenName) && $token === Session::get($tokenName)) {
Session::delete($tokenName);
return true;
}
return false;
}
}
I got errors saying my email var is empty, besides that I have problems with the regex, which seems to be range out of order in character class, I guess it is some stupid mistake, for that I have much to learn
<?php
include_once('../resources/config.php');
class register
{
private $username;
private $password;
private $passmd5;
private $email;
private $errors;
private $token;
private $db;
public function __construct()
{
$this->db = new config();
$this->db = $this->db->dbConnect();
$this->errors = array();
$this->username = $this->regex($_POST['user']);
$this->password = $this->regex($_POST['pass']);
$this->email = $this->regex($_POST['email']);
$this->token = $this->regex($_POST['token']);
$this->passmd5 = md5($this->password);
}
public function process()
{
if($this->valid_token() && $this->valid_data())
$this->register();
}
public function regex($var)
{
$reggie = preg_replace('/[^a-zA-ZO-90.]/','',$var);
return $reggie;
}
public function register()
{
$this->db->prepare("insert into users(name, pass) values ('($this->username)','($this->passmd5)')");
if(rowCount() < 1)
$this->errors() == "form has failed you";
}
public function show_errors()
{
foreach ($this->errors as $key => $value) {
echo $value."</br>";
}
}
public function valid_data()
{
if(empty($this->username))
$this->errors() == 'invalid username';
if(empty($this->password))
$this->errors() == 'invalid password';
if(empty($this->email) || !ereg('/^[^\W][a-zA-Z0-9_]+(\.[a-zA-Z0-9_]+)*\#[a-zA-Z0-9_]+(\.[a-zA-Z0-9_]+)*\.[a-zA-Z]{2,4}$/', $this->email))
$this->errors() == 'invalid email';
return count ($this->errors)? 0:1;
}
public function valid_token()
{
}
}
?>
$obj_reg = new register();
if($obj_reg->process())
{
echo 'succes';
}else
{
$obj_reg->show_errors();
}
}
$token = $_SESSION['token'] = md5(uniqid(mt_rand(), true));
?>
<form method="post" action="index.php?page=register.php" >
<table>
<tr><td>username:</td><td> <input type="text" name="user"/></td></tr>
<tr><td>password:</td><td> <input type="password" name="pass"/></td></tr>
<tr><td>email:</td><td> <input type="text" name="email"/></td></tr>
</table>
<input type="hidden" name="token" value="<?=$token;?>"/>
<input type="submit" name="register" value="register"/>
</form>
For the email regex you should replace:
if(empty($this->email) || !ereg('/^[^\W][a-zA-Z0-9_]+(\.[a-zA-Z0-9_]+)*\#[a-zA-Z0-9_]+(\.[a-zA-Z0-9_]+)*\.[a-zA-Z]{2,4}$/', $this->email))
$this->errors() == 'invalid email';
With:
if (!filter_var($this->email, FILTER_VALIDATE_EMAIL))
$this->errors() == 'invalid email';
Use
$this->errors[] = "invalid foo";
instead of
$this->errors() == "invalid foo";
<?php
require_once('../resources/config.php');
class register
{
private $username;
private $password;
private $passmd5;
private $errors;
public function process()
{
if($this->valid_data())
{
$this->send();
}
else
{
echo "mama";
}
}
public function regex($var)
{
$reggie = preg_replace('/[^A-Za-z0-9:.\/_-]/','',$var);
return $reggie;
}
public function send()
{
mysql_query("INSERT INTO 'users' WHERE name='.$this->username.' pass='.$this->password.'");
}
public function checking($name, $pass)
{
$this->errors = array();
$this->username = $this->regex($name);
$this->password = $this->regex($pass);
$this->passmd5 = md5($this->password);
}
public function show_errors()
{
foreach ($this->errors as $key => $value) {
echo $value."</br>";
}
}
public function valid_data()
{
if(empty($this->username))
$this->errors[] = 'invalid username';
if(empty($this->password))
$this->errors[] = 'invalid password';
return count ($this->errors);
}
}
?>