PHP: Script showing parsing syntax error - php

I found an issue I can't seem to find a solution to. I am using a singleton class / method that return a single static PDO object. When I try to declare a static reference to the object (http://i.imgur.com/EhKZuVH.png), I get http://i.imgur.com/jUPMQrO.png . How would I go about fixing this?
Game Class:
<?php
include_once('functions.php');
include_once('database.php');
$_codeRegex = '^([a-zA-Z0-9]{4,7})$';
class Game
{
public $Id = "";
public $Name = "";
private static $connection = Database::Connect();
public function __construct($id, $name)
{
$this->Id = $id;
$this->Name = $name;
}
}
?>
My singleton Class:
<?php
require_once('config.php');
CONST CONNECTION_FORMAT = 'mysql:host=%1$s;dbname=%2$s;charset=utf8';
class Database
{
private static $cont = null;
public function __construct() {
exit('Initialize function is not excessible.');
}
public static function Connect()
{
if (self::$cont == null)
{
try
{
$pdoConstuct = sprintf(CONNECTION_FORMAT, DB_SERVER, DB_NAME);
self::$cont = new PDO($pdoConstuct, DB_USER, DB_PASS);
self::$cont->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
}
catch(PDOException $e) { return false; }
}
return self::$cont;
}
public static function Disconnect()
{
self::$cont = null;
}
}
?>

PHP is not Java where you can define property values like this.
What you can do here is simply put property initialization into the contructor, like this:
private static $connection;
public function __construct($id, $name)
{
$this->Id = $id;
$this->Name = $name;
self::$connection = Database::Connect();
}
When you define a class property in PHP you can not set its default value to instance of a class.

Related

PHP A Good way to pass the PDO Object into other Main classes

im new to PHP OOP, now i was woundering if there is a better way to use the Database Class then just extending it over all.
For Example i am having 3 main classes: Employee, Customer, Article. each of this classes have a subclasses which extends form. what i have done until now is extand the Db class on each of these 3 main classes.
My DB class:
class DbController{
private $serverName;
private $userName;
private $userPass;
private $dbName;
private $charSet;
private $pdo;
protected function __construct() {
try {
$this->serverName = "localhost";
$this->userName = "blabla";
$this->userPass = "***";
$this->dbName = "blabla";
$this->charSet = "utf8mb4";
$dsn = "mysql:host=".$this->serverName."; dbname=".$this->dbName."; charset=".$this->charSet;
$pdo = new PDO($dsn, $this->userName, $this->userPass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->pdo = $pdo;
return $pdo;
} catch (PDOException $err) {
die($err->getMessage());
}
}
protected function getPdo(){
return $this->pdo;
}
public function __debugInfo(){
$properties = get_object_vars($this);
unset($properties['serverName']);
unset($properties['userName']);
unset($properties['userPass']);
unset($properties['pdo']);
unset($properties['dbName']);
unset($properties['charSet']);
return $properties;
}
}
one Of the Main classes (Employee):
<?php
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
include_once "DbController.cls.php";
class Employee{
public $id;
protected $name;
protected $username;
protected $scoore;
protected $dbTable = "employee";
protected PDO $pdo;
public function __construct($info = NULL) {
// pls notice that The DbController() is a protected Constructor.
$this->pdo = new DbController();
if (isset($info)) {
$this->id = $info["id"];
$this->name = $info["name"];
$this->username = $info["username"];
$this->scoore = $info["scoore"];
}
}
// Setters and Getters ......
then there is a sub class of Employee called EmployeeMng. this subclass contains functions such as login or signup. also this subclass handles the POST requests coming froom the client side.
include_once "../classes/Employee.cls.php";
$_POST = json_decode(file_get_contents('php://input'), true);
class EmployeeManagement extends Employee{
public function __construct() {
if (isset($_SESSION['empID'])) {
parent::__construct();
parent::__construct($this->fetchEmpInfo($_SESSION['empID']));
} else {
parent::__construct();
}
}
public function signIn($username, $password){
$retrunArray = array('code' => 0, 'msg' => "No Data Returned");
$checkCredential = $this->checkCredential($username, $password);
if ($checkCredential['code'] == 1) {
try {
$getEmpID = $this->pdo->prepare("SELECT `id` FROM `employee` WHERE `username`=? AND `password`=? LIMIT 1;");
$getEmpID->execute([$username, $password]);
$empId = $getEmpID->fetch(PDO::FETCH_ASSOC)['id'];
$_SESSION['empID'] = $empId;
$retrunArray['code'] = 1;
$retrunArray['msg'] = "Erfolgreich eingeloggt";
return $retrunArray;
} catch (PDOException $err) {
$retrunArray['code'] = 0;
$retrunArray['msg'] = $err->getMessage();
return $retrunArray;
}
} else{
// In case of DB Error
return $checkCredential;
}
}
// Request Handler Begin
$employeeService = new EmployeeManagement();
header('Content-Type: application/json');
// Login:
if (isset($_POST["signIn"])) {
$signIn = $employeeService->signIn($_POST["username"], $_POST["password"]);
echo json_encode($signIn);
}
Now i tried to declare the db class in the Employee constructor. but i keep getting the error Call to protected DbController::__construct() from scope Employee. is there a clean way to do that?
In general, you'd create your database object outside of this class and then inject it as a parameter. This is called Dependency Injection and is a Good Thing™.
Then you'd use that parameter within your class-specific methods. So your employee class would look something like this:
class Employee
{
protected $db;
public function __construct(PDO $db)
{
$this->db = $db;
}
public function find($id)
{
// or whatever your query looks like
$stmt = $this->db->query('SELECT * FROM EMPLOYEE WHERE id = :id');
// $row = ...
return $row;
}
public function getAll()
{
$stmt = $this->db->query('SELECT * FROM EMPLOYEE');
// whatever
}
}
And then to use that class, you'd instantiate a database object, and then pass that to the Employee:
$db = new PDO();
$employee = new Employee($db);
$steve = $employee->find(1);
You should not do this:
class Employee
{
public $db;
public function __construct(PDO $db)
{
$this->db = $db;
}
}
$db = new PDO();
$employee = new Employee($db);
$steve = $employee->db->query('...');
Or this:
class Employee extends PDO
{
// ...
}
$employee = new Employee($db);
$employee->query('...');
Inheritance is not the way to go here. If you inherit DbController each class will instantiate a new PDO connection.
Instead, instantiate DbController first, then call its getPDO() method to obtain a PDO connection object to pass into your other classes as a parameter to their constructors. You'll need to change the DbController method declaration to public instead of private
Like this:
class DbController{
private $serverName;
private $userName;
private $userPass;
private $dbName;
private $charSet;
private $pdo;
public function __construct() {
try {
$this->serverName = "localhost";
$this->userName = "blabla";
$this->userPass = "***";
$this->dbName = "blabla";
$this->charSet = "utf8mb4";
$dsn = "mysql:host=".$this->serverName."; dbname=".$this->dbName."; charset=".$this->charSet;
$pdo = new PDO($dsn, $this->userName, $this->userPass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->pdo = $pdo;
// return $pdo; No need for this. The constructor doesn't use it.
} catch (PDOException $err) {
die($err->getMessage());
}
}
public function getPdo(){
return $this->pdo;
}
}
class Employee {
private $PDO;
public function __construct(PDO $pdo) {
$this->PDO = $pdo
}
public function getEmployee($id) {
// get employee details using $this->PDO as your connection object
}
}
then your main program becomes something like
require_once('DbController.php');
require_once('Employee.php');
$DB = new DbController();
$emp = new Employee($DB->getPDO());
$id = 'some employee reference';
$employeeDetails = $emp->getEmployee($id);

PHP Singleton pattern, fatal error when calling getter

I am pretty new to PHP and try to learn it the OOP way as I have an understanding of it. My problem is I have no idea why I am getting the null error below when I try to get the mysqli connection.
Fatal error: Uncaught Error: Call to a member function getConn() on
null
<?php
class ConnectDB
{
private $conn;
private function __construct()
{
$this->conn = new mysqli('localhost', 'root', 'root', 'gs');
$this->checkConnection();
}
public function getConn()
{
return $this->conn;
}
/**
* #return ConnectDB
*/
public static function getInstance()
{
static $instance = null;
if($instance == null)
{
$instance == new ConnectDB();
}
return $instance;
}
public function checkConnection()
{
if($this->conn->connect_errno)
{
echo "Can't connect to Database: " .mysqli_connect_error();
exit();
}
else
{
echo "Connected!";
}
}
}
$conn = ConnectDB::getInstance()->getConn();
In your getInstance method, where you create the class instance you wrote $instance == new ConnectDB();. Use a single = for assignments.
I don't think that your getInstance method is a singleton at all. You are initializing the variable $instance in every call to null, so you should get a new instance every time.
Try it like this:
class ConnectDB
{
private $conn;
private static $instance = null;
...
public static function getInstance()
{
if(self::$instance == null)
{
self::$instance == new ConnectDB();
}
return self::$instance;
}
...
See if you can make this work:
<?php
class ConnectDB {
private $_connection;
private static $_instance; //The single instance
private $_host = "localhost";
private $_username = "root";
private $_password = "root";
private $_database = "gs";
//
public static function getInstance() {
if(!self::$_instance) { // If no instance then make one
self::$_instance = new self();
}
return self::$_instance;
}
// Constructor
private function __construct() {
$this->_connection = new mysqli($this->_host, $this->_username, $this->_password, $this->_database);
// Error handling
if(mysqli_connect_error()) {
trigger_error(
"Failed to conencto to MySQL: " . mysql_connect_error(),E_USER_ERROR
);
} else{
echo "Connected!";
}
}
private function __clone() { }
public function getConn() {
return $this->_connection;
}
$db = ConnectDB::getInstance();
$mysqli = $db->getConn();
}
?>

Static method calling result of mysql query

I have
class Check
{
public function __construct()
{
$this->db = new Database();
}
public function query()
{
$login = Session::get("login");
$sth = $this->db->prepare('SELECT admin FROM accounts WHERE login=:login');
$sth->execute(array(':login' => $login));
$result = $sth->fetch(PDO::FETCH_NUM);
return $result[0];
}
public static function admin()
{
echo self::query();
}
}
I have Database class in another place with PDO connection.
class Database extends PDO
{
public function __construct()
{
parent::__construct('mysql:host=localhost;dbname=name','root','pass');
$this->query('SET NAMES utf8');
}
}
So after Check::admin() code I get error:
Undefined property: View::$db
Why?
You are using a static method, that wants to use a instance variable.
Your admin method calls the query method, and the query method is using the db instance variable. As your class is not instantiated, the db variable does not exists.
My suggestion would be to make the admin method non static and use your code like this:
$mycheck = new Check();
$mycheck->admin();
or, if you are on php 5.4 and want to stick with a oneliner:
(new Check())->admin();
update
note: Do not create the db class in the constructor, but inject it:
public function __construct(Database $db)
{
$this->db = $db;
}
Sorry this is not direct answer for your question but your code has some issues so take some time and examine this and ask if it's not clear for you.
<?php
class Check {
protected $_db;
public function __construct(Database $db) {
$this->_db = $db;
}
public function query(ISession $sessionData) {
//WHY IS THE SESSION STATIC?
//$login = Session::get("login");
$sth = $this->_db->Connection()->prepare('SELECT admin FROM accounts WHERE login=:login');
$sth->execute(array(':login' => $sessionData->get("login")));
$result = $sth->fetch(PDO::FETCH_NUM);
return $result[0];
}
public function admin(ISession $sessionData) {
// REALLY BAD TO ECHO HERE
echo $this->query($sessionData);
}
}
class Database {
private $_name;
private $_password;
private $_connStr;
private $_settings;
private $_pdo;
public function __construct($connstr, $name, $password, array $settings = array()) {
$this->_name = $name;
$this->_password = $password;
$this->_connStr = $connstr;
$this->_settings = $settings;
}
public function Connection() {
if ($this->_pdo == NULL) {
$this->_pdo = new PDO($this->_connStr, $this->_name, $this->_password);
}
return $this->_pdo;
}
/* other fancy methods */
public function Close() {
$this->_pdo = NULL;
}
public function __destruct() {
$this->Close();
}
}
And i don't see why you need a Check class for all this becouse if i were you i would create somethinf like this:
$currentSession = Session::GetCurrent();
$currentSession->User()->IsInRole('admin');
Note that the session is not static and if i would write a more complete solution i would avoid Session::GetCurrent() call becouse the current session would be a field in some class' instance (HttpApplication for example).

How can I pass DB connection object from one class to another?

I'm trying to pass a PDO connection object from one class to another. But I'm not being very successfull. And I only want to instanciate only one PDO object.
With the help from dqhendricks and awm I managed to get the following solution working:
class Factory {
function createUser($id = NULL) {
return new User(Conn::get_conn(), $id);
}
function createApplication($id = NULL) {
return new User(Conn::get_conn(), $id);
}
}
class Conn {
private static $conn = NULL;
private function __construct() {}
private static function init() {
$conf = self::config();
try {
self::$conn = new PDO($conf['dsn'], $conf['user'], $conf['pass']);
}
catch (PDOException $e) {
echo $e->getMessage();
}
}
public static function get_conn() {
if (!self::$conn) { self::init(); }
return self::$conn;
}
private static function config($cfg_file = 'sl.config') {
$config = parse_ini_file('/../'.$cfg_file);
$conf = array();
$conf['user'] = $config['db_user'];
$conf['pass'] = $config['db_password'];
$conf['dsn'] = 'mysql:dbname='.$config['db_name'].';host='.$config['db_host'];
return $conf;
}
}
In my UserDAO class, I can now do this:
class UserDAO {
private $db;
private $id;
function UserDAO (&$db, $id) {
$this->db = &$db;
$this->id = &$id;
}
public function getRows($sql)
{
$result = $this->db->query($sql);
$row = $result->fetch(PDO::FETCH_ASSOC);
return $row;
}
function getUsers($limit = 10) {
$sql ="SELECT * FROM sl_store LIMIT $limit";
return $this->getRows($sql);
}
}
//My User class
class User extends UserDAO implements iUser {}
// And to test it working:
$user1 = Factory::createUser('5');
$user2 = Factory::createApplication('7');
How about defining an abstract class which gives you the PDO object on request?
E.g.
abstract class Db {
private static $x = null;
private static function init() {
try {
self::$x = new PDO(...);
} catch (PDOException $e) {
...
}
}
public static function getX() {
if (!self::$x) self::init();
return self::$x;
}
}
no need to have your class create an instance of itself if all you want is an instance of a different object back. maybe make a static method in Conn to return an instance of a db connection.
class Conn {
// prevent new statement
private __construct() {}
public static return_pdo() {
blah
blah
blah
return $db;
}
public static config($file) {
do stuff
}
}
then call statically
$pdo = Conn::return_pdo();
It's because new Conn() returns $Conn object, not the value from $Conn->Conn() method.
Try this:
class Conn{
function Conn() {
$db = new PDO($conf['dsn'], $conf['user'], $conf['pass']);
}
function get_db() {
return $this->db;
}
}
class Factory {
function createUser($id = NULL) {
$new_conn = new Conn();
$db = $new_conn->get_db();
}
}

Using a database class in my user class

In my project I have a database class that I use to handle all the MySQL stuff. It connects to a database, runs queries, catches errors and closes the connection.
Now I need to create a members area on my site, and I was going to build a users class that would handle registration, logging in, password/username changes/resets and logging out. In this users class I need to use MySQL for obvious reasons... which is what my database class was made for.
But I'm confused as to how I would use my database class in my users class. Would I want to create a new database object for my user class and then have it close whenever a method in that class is finished? Or do I somehow make a 'global' database class that can be used throughout my entire script (if this is the case I need help with that, no idea what to do there.)
Thanks for any feedback you can give me.
Simple, 3 step process.
1/ Create a database object.
2/ Give it to your user class constructor.
3/ Use it in the user methods.
Little example.
File Database.class.php :
<?php
class Database{
public function __construct(){
// Connects to database for example.
}
public function query($sqlQuery){
// Send a query to the database
}
[...]
}
In User.class.php :
<?php
class User{
private $_db;
public function __construct(Database $db){
$this->_db = $db;
}
public function deleteUser(){
$this->_db->query('DELETE FROM Users WHERE name = "Bobby"');
}
}
Now, in userManager.php for example :
<?php
$db = new Database();
$user = new User($db);
// Say bye to Bobby :
$user->deleteUser();
If you want the current trendy name of this old technique, google "Dependency Injection". The Singleton pattern in php will fade away soon.
As he said, put all your functions in the database class and use the database object to access those functions from your user class. This should be the best method in your case.
Eg:
global $database;
userclassvar = $database->doSomething();
What I like to do is make the database class with the Singleton pattern in mind. That way, if you already have a database object, it just retrieves it, otherwise creates a new one. For example:
Database.class.php
class Db
{
protected static $_link;
private function __construct()
{
// access your database here, establish link
}
public static function getLink()
{
if(self::_link === null) {
new Db();
}
return self::_link;
}
// etc.
}
User.class.php
class User
{
protected $_link; // This will be the database object
...
public function __construct()
{
$this->_link = Db::getLink();
}
}
And now you can use User's $_link property to do the database functions, like $this->_link->query(...). You don't necessarily have to put the Db::getLink() in the constructor if your class doesn't have to interact with the database that much.
Since you are using the database as an object, why not just add methods to the object that your "users class" can employ to take care of the things it needs to do. The users class can contain a pointer to the database class. The database class will protect your database, and assure that the users class is using it appropriately.
Here is a solution using PDO.
<?php
class Database {
private static $dbh;
public static function connect() {
$host = "mysql:dbname=YOUR_DB_NAME;host=YOUR_DB_SERVER";
$username = "YOUR_USERNAME";
$password = "YOUR_PASSWORD";
try {
self::$dbh = new PDO( $host, $username, $password );
self::$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
self::$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
self::$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
} catch( PDOException $e ){
$error_message = $e->getMessage();
exit();
}
return self::$dbh;
}
}
class MYObject {
public static $dbh = null;
public function __construct(PDO $db = null) {
if($db === null){
$this->dbh = Database::connect();
} else {
$this->dbh = $db;
}
}
}
class User extends myObject {
public function __construct($id = null, PDO $db = null) {
if($db === null){
parent::__construct();
} else {
parent::__construct($db);
}
if($id !== null){
return $this->select($id);
}
}
public function select($id) {
$retVal =false;
try {
$stmt = $this->dbh->prepare("SELECT...");
$stmt->execute();
if( $stmt->rowCount()==1 ){
$row = $stmt->fetchAll(PDO::FETCH_ASSOC);
$retVal =json_encode($row);
}
} catch (PDOException $e ) {
$error_message = $e->getMessage();
exit();
}
return $retVal;
}
}
?>
I think the better aproach would be to create the database class that instatiate right away on its own on a database.php and then include it on user.php. then every time you create a function that needs a database, you globalise the database object.
Check this.
databse.php
<?php
require_once ('includes/config.php');
class MysqlDb{
public $connection;
private $last_query;
private $magic_quotes_active;
private $real_escape_string_exists;
public function __construct() {
$this->open_connection();
$this->magic_quotes_active = get_magic_quotes_gpc();
$this->real_escape_string_exists = function_exists( "mysql_real_escape_string" );
}
public function open_connection() {
$this->connection = mysql_connect(DBHOST,DBUSER,DBPASS);
if(!$this->connection){
die("Could not Connect ".mysql_error());
}else{
$db = mysql_select_db(DB, $this->connection);
}
}
public function close_connection(){
if(isset($this->connection)){
mysql_close($this->connection);
unset($this->connection);
}
}
public function query($sql){
$this->last_query = $sql;
$results = mysql_query($sql, $this->connection);
$this->comfirm_query($results);
return $results;
}
private function comfirm_query($results){
if(!$results){
$output = "Query Failed " .mysql_error()."<br />";
$output .= "Last Query: " . $this->last_query;
die($output);
}
}
public function escape_value($value){
if( $this->real_escape_string_exists ) {
if($this->magic_quotes_active ) { $value = stripslashes( $value ); }
$value = mysql_real_escape_string( $value );
} else {
if( !$this->magic_quotes_active ) { $value = addslashes( $value ); }
}
return $value;
}
public function fetch_array($results){
return mysql_fetch_array($results);
}
public function num_row($results){
return mysql_num_rows($results);
}
public function insert_id(){
return mysql_insert_id($this->connection);
}
public function affected_row(){
return mysql_affected_rows();
}
}
$database = new MysqlDb();
?>
here is the user.php
<?php
require_once ('includes/database.php');
class User {
public $id;
public $fName;
public $lName;
Public $userName;
public $password;
public $email;
public $acess;
public static function find_all(){
global $database;
return self::find_by_sql("SELECT * FROM users");
}
public static function find_by_id($id=0){
global $database;
$results_array = self::find_by_sql("SELECT * FROM users where id={$id}");
return !empty($results_array)? array_shift($results_array) : false;
}
public static function find_by_sql($sql){
global $database;
$results = $database -> query($sql);
$object_array = array();
while($row = $database -> fetch_array($results)){
$object_array[] = self::instantiate($row);
}
return $object_array;
}
public static function instantiate($row){
$user = new self;
foreach($row as $attribute => $value){
if($user -> has_attribute($attribute)){
$user -> $attribute = $value;
}
}
return $user;
}
private function has_attribute($attribute){
$object_vars = get_object_vars($this);
return array_key_exists($attribute, $object_vars);
}
}
?>

Categories