I'm trying to learn OOP, and some of its concept. I've following class for users:
class Users
{
private $host = DB_HOST;
private $user = DB_USERNAME;
private $pass = DB_PASSWORD;
private $dbname = DB_NAME;
private $conn;
private $stmt;
public $error;
function __construct()
{
$dsn = 'mysql:host='.$this->host.';dbname='.$this->dbname.';charset=utf8';
$options = array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
);
try {
$this->conn = new PDO($dsn,$this->user,$this->pass,$options);
} catch (PDOException $e) {
$this->error = $e->getMessage();
}
}
private function mysql_execute_query($sql,$params)
{
$this->stmt = $this->conn->prepare($sql);
$this->stmt->execute($params);
return $this->$stmt;
}
public function find_user_by_provider_uid($provider,$provider_uid)
{
$sql = 'SELECT * FROM users WHERE provider = :provider AND provider_uid = :provider_uid LIMIT 1';
$params = array(
':provider' => $provider,
':provider_uid' => $provider_uid
);
$result = $this->mysql_execute_query($sql,$params);
return $result->fetch();
}
}
First of all is there some tip that comes to mind for structuring this code better? or using more features of oop?
Second, it fails with following error:
PHP Notice: Undefined variable: stmt
PHP Fatal error: Cannot access empty property
Both of this lines refer to return $this->$stmt; inside mysql_execute_query
My hunch is that it has something to do with it being private function. But I cannot tell.
Any ideas?
Here the error:
return $this->$stmt;
But should be:
return $this->stmt;
Related
I recently started to resurrect an old PHP4.# website. In doing so I've been trying to figure out the conversion to PDO. After so many different attempts at PDO structure I'm getting lost and my code keeps getting more and more wild. I believe the problem is that I'm not correctly instantiating the pdo class but have failed using several different methods.
Fatal error: Uncaught Error: Call to undefined method DBInsert::__construct() in /home/folder/database/insert.php:36
mysqlhelper.php
<?php
class MySQLHelper
{
private $link;
private $db;
private $user;
private $pass;
var $pdo;
public function __construct()
{
$host = 'localhost';
$db = 'dbname';
$user = 'username';
$pass = 'supersecret';
$port = '1111';
$options = [
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
\PDO::ATTR_EMULATE_PREPARES => false,
];
try {
$dsn = "mysql:host=$host;dbname=$db;port=$port";
$this->pdo = new PDO($dsn, $user, $pass, $options);
return $this->pdo;
} catch (\PDOException $e) {
throw new \PDOException($e->getMessage(), (int)$e->getCode());
echo "Connection failed";
}
}
function __destruct()
{
// Closing connection
$this->pdo = null;
}
public function query($query)
{
// Performing SQL query
$result = $this->pdo->query($query) or die('Query failed: ' . mysql_error());
return $result;
}
insert.php
<?php
include "../helpers/mysqlhelper.php";
class DBInsert
{
private $helper;
private $nations;
private $nations_updated;
private $stagedslots;
private $stagednations_new; // nations that need to be inserted
private $stagednations_old; // nations that need to be updated
var $pdo;
//this function was previously called __construct() prior to my 11/22/20 updates
function somethingelse()
{
$this->helper = new MySQLHelper();
$this->stagedslots = array();
$this->nations_updated = array();
$this->nations = array();
$q = "SELECT * FROM `nations`";
$result = $this->helper->query($q);
$result = $this->helper->getResultArray($result);
foreach ($result as $val)
{
$this->nations[$val["id"]] = $val;
}
}
public function clearSlots()
{
$sql = "DELETE FROM `slots`;";
$object = new MySQLHelper;
$object->__construct();
line 36 $stmt = $this->__construct()->prepare($sql);
$stmt->execute();
}
For line 36 I've also tried $stmt = $this->pdo->prepare($sql); which yields errors also.
Appreciate any suggestions.
$object = new MySQLHelper;
$object->__construct();
$stmt = $this->__construct()->prepare($sql);
You are writing the same thing three times here:
You make a new object $object and then you do not need to call __construct because by making the object it automatically calls the constructor already.
$sql = "DELETE FROM `slots`;";
$object = new MySQLHelper; //automaticcally calls the constructor
$stmt = $object->prepare($sql);
$stmt->execute();
$stmt->close(); // close connection.
READ THIS
I am new to using PHPUnit and i am trying to test function getAllTasks() which need to fetch all tasks from database. I tried everything but i am just making my code worse. So please help me to solve the problem. TaskTest.php is something i tried to make test but it dont works. And sure if there are better ways to do something, i like to learn new stuff too. Here is my code:
EDIT: I changed code for TaskTest.php and i managed to get test pass. Can someone please tell me if this is good way to test this function, or there are better ways? Thanks!
Task.php
<?php
require_once 'Database.php';
class Task {
private $db;
public function __construct() {
$this->db = new Database;
}
public function getAllTasks() {
$this->db->query('SELECT * FROM tasks');
$results = $this->db->resultSet();
return $results;
}
}
Database.php
<?php
class Database {
private $host = 'localhost';
private $user = 'root';
private $pass = '123456';
private $dbname = 'todolist';
private $dbh;
private $stmt;
private $error;
public function __construct(){
// Set DSN
$dsn = 'mysql:host=' . $this->host . ';dbname=' . $this->dbname;
$options = array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
);
// Create PDO instance
try {
$this->dbh = new PDO($dsn, $this->user, $this->pass, $options);
} catch(PDOException $e){
$this->error = $e->getMessage();
echo $this->error;
}
}
public function query($sql){
$this->stmt = $this->dbh->prepare($sql);
$this->execute();
}
public function execute(){
return $this->stmt->execute();
}
public function resultSet(){
$this->execute();
return $this->stmt->fetchAll(PDO::FETCH_ASSOC);
}
}
TaskTest.php
<?php
require_once './src/Task.php';
require_once './src/Database.php';
use PHPUnit\Framework\TestCase;
class TaskTest extends TestCase {
public function testGetAllTasks() {
$table = array(
array(
'task_id' => '1',
'task_desc' => 'Task One Test'
),
array(
'task_id' => '2',
'task_desc' => 'Task Two Test'
)
);
$dbase = $this->getMockBuilder('Database')
->getMock();
$dbase->method('resultSet')
->will($this->returnValue($table));
$expectedResult = [
'task_id' => '1',
'task_desc' => 'Task One Test',
];
$task = new Task();
$actualResult = $task->getAllTasks();
$this->assertEquals($expectedResult, $actualResult[0]);
}
}
You pass the mock to the Task class constructor, but it doesn't do anything with it.
$task = new Task($resultSetMock);
Updated the code so that it will be used:
class Task {
private $db;
public function __construct( ?Database $db = null ) {
// set the db if none is provided
if( is_null($db) )
{
$db = new Database;
}
$this->db = $db;
}
// ...
}
I have a:
class Person
{
public $data;
public function __construct($name) {
$database = new Database;
$database->prepare('SELECT * FROM persons where name = :name');
$database->bindParam(':name', $name);
$database->execute();
$this->data = $database->fetch();
}
}
and i´m creating persons like this:
$jim = new Person('Jim');
$mike = new Person('Mike');
and this is my database class
class Database
{
private $host = 'localhost';
private $user = 'test';
private $pass = '123';
private $dbname = 'test';
private $dbh;
private $error;
private $stmt;
public function __construct()
{
$dsn = 'mysql:host=' . $this->host . ';dbname=' . $this->dbname;
$options = array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
);
try{
$this->dbh = new PDO($dsn, $this->user, $this->pass, $options);
}
catch(PDOException $e){
$this->error = $e->getMessage();
echo $this->error;
}
}
public function prepare($query)
{
$this->stmt = $this->dbh->prepare($query);
}
public function bindParam($key, $val)
{
$this->stmt->bindParam($key, $val);
}
public function execute()
{
$this->stmt->execute();
}
public function fetch()
{
return $this->stmt->fetch(PDO::FETCH_ASSOC);
}
}
I´m getting this message very often
Warning: PDO::__construct(): MySQL server has gone away
I want to confirm if this approach is correct. calling the database in the constructor?
How can i know if the created person exists (i mean exist in the database)
should i do something like this?
$jim = new Person('Jim');
if($jim->data) {
echo 'person exists in the db';
}
thank you
I was advised to rewrite how I handle connection, as it is now, my class creates new connection on every instance of the object. How would I change it to share connection between multiple objects created with this class?
/**
* This is Users class, deals with finding, updating, creating user
*/
class Users
{
private $host = DB_HOST;
private $user = DB_USERNAME;
private $pass = DB_PASSWORD;
private $dbname = DB_NAME;
private $conn;
private $stmt;
public $error;
function __construct()
{
$dsn = 'mysql:host='.$this->host.';dbname='.$this->dbname.';charset=utf8';
$options = array(
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
);
try {
$this->conn = new PDO($dsn,$this->user,$this->pass,$options);
} catch (PDOException $e) {
$this->error = $e->getMessage();
}
}
private function mysql_execute_query($sql,$params)
{
$this->stmt = $this->conn->prepare($sql);
$this->stmt->execute($params);
return $this->stmt;
}
public function find_user_by_provider_uid($provider,$provider_uid)
{
$sql = 'SELECT * FROM users WHERE provider = :provider AND provider_uid = :provider_uid LIMIT 1';
$params = array(
':provider' => $provider,
':provider_uid' => $provider_uid
);
$result = $this->mysql_execute_query($sql,$params);
return $result->fetch(PDO::FETCH_ASSOC);
}
}
If you really need that, define your property as static:
private static $conn;
Of course, make sure that accessing to that will be done right (i.e. not via $this, but via self (or class name) since it will be no longer belong to instance)
That, however, isn't a good practice: if you want manage connections - manage how many times you'll instantiate your class.
I've just started to learn OOP PHP and i'm trying create class that will do connection to my data base.
The code:
class DB_CONNECT
{
private $host ;
private $dbName ;
private $userName ;
private $password;
private $db;
public function __construct($host,$dbName,$userName,$password){
$this->host = $host;
$this->dbName = $dbName;
$this->userName = $userName;
$this->password = $password;
try {
$this->db = new PDO('mysql:host='.$this->host.';dbname='.$this->dbName.';charset=utf8',$this->userName,$this->password);
$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $this->db;
} catch (Exception $e) {
ECHO $e->getMessage();
}
}
}
$db = new DB_CONNECT("localhost", "oopcms","viktor","viktor");
function select($db){
$query = $db->prepare("SELECT * FROM `test`");
$query->execute();
$row = $query->fetchAll(PDO::FETCH_ASSOC);
return $row;
}
$x = select($db);
var_dump($x);
But I am getting this error:
Fatal error: Call to undefined method DB_CONNECT::prepare();
What I understand is that the PDO object couldn't be created. Can you give some guidance please?
Learning OOP is not the reason for creating pointless classes.
Unfortunately, you created one. PDO don't need a class to be built on top of it. Just leave it as is.
So, instead of
$db = new DB_CONNECT("localhost", "oopcms","viktor","viktor");
make it
$db = new PDO("localhost", "oopcms","viktor","viktor");
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
that would be way clearer and useful
who interested here is the solution of this and Pekka and Your Common Sense thank you for a tip:)
class Select
{
private $query;
private $dbh;
private $row;
public function __construct(){
$this->dbh = new DB_CONNECT("localhost", "oopcms","viktor","viktor");
}
public function select(){
$this->query = $this->dbh->db->prepare("SELECT * FROM `test`");
$this->query->execute();
$this->row = $this->query->fetchAll(PDO::FETCH_ASSOC);
return $this->row;
}
}
$sel = new Select();
$s = $sel->select();
var_dump($s);