I need to get data, to check and send to db.
Programming with PHP OOP.
Could you tell me if my class structure is good and how dislpay all data?. Thanks
<?php
class Database{
private $DBhost = 'localhost';
private $DBuser = 'root';
private $DBpass = 'root';
private $DBname = 'blog';
public function connect(){
//Connect to mysql db
}
public function select($rows){
//select data from db
}
public function insert($rows){
//Insert data to db
}
public function delete($rows){
//Delete data from db
}
}
class CheckData{
public $number1;
public $number2;
public function __construct(){
$this->number1 = $_POST['number1'];
$this->number2 = $_POST['number2'];
}
function ISempty(){
if(!empty($this->$number1)){
echo "Not Empty";
$data = new Database();
$data->insert($this->$number1);
}
else{
echo "Empty1";
}
if(!empty($this->$number2)){
echo "Not Empty";
$data = new Database();
$data->insert($this->$number2);
}
else{
echo "Empty2";
}
}
}
class DisplayData{
//How print all data?
function DisplayNumber(){
$data = new Database();
$data->select();
}
}
$check = new CheckData();
$check->ISempty();
$display = new DisplayData()
$display->DisplayNumber();
?>
That's horrible piece of code.
For database communication use PDO. It's not perfect, but it's fine.
Every time you'll need database you'll connect with that db?
Database::insert() etc. would have to be a true magician to guess where its parameter should be inserted
You need a better IDE to show your undefined variables. I use PHPStorm.
You need some dependency injection. Use encapsulation. Just follow SOLID.
Second to last thing, don't echo from within objects. You can't unit test effectively your code that way.
You might also try some TDD.
You're going at things wrong here, I think. What you are constructing is a wrapper around already-existing database functions. Thing is, those functions already defined to do exactly what you want - the object oriented approach here serves no real purpose since it can only connect to one database and the methods are not really well defined and seem to act as pure pass-throughs to the underlying layer.
As others have mentioned, the code you seem to be going at here is not going to suit your purposes. Something like PDO will serve you well and its already built in to PHP. You don't need to re-invent the wheel for such common code as accessing a database.
Learning a few core Object Orientation principles will do you good too - look at encapsulation and code re-use first. They'll help in the future when you have to maintain that code you write!
Related
I'm just trying to master the art of using classes in PHP and have come across a concern.
For security reasons, I sometimes use two database connections in my application; one with read-only privileges and one with full read/write. Unfortunately, I wasn't really thinking about this when I started to build a few classes.
So, I have a database class, which is essentially a pointless PDO wrapper (pointless because PDO is a wrapper), but thought it'd be good practice to write one anyway and I may extend PDO later too. This is what I did:
<?php
class Database {
private $dbh;
public function __construct($accessLevel = NULL, $credentials = NULL) {
if (gettype($credentials) === 'array') {
$dsn = 'mysql:host='.$credentials['dbHost'].';dbname='.$credentials['dbName'];
$options = array (
PDO::ATTR_PERSISTENT => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
);
if ($accessLevel == "public") {
$this->dbh = new PDO($dsn, $credentials['publicUser'], $credentials['publicPassword'], $options);
} else if ($accessLevel == "private") {
$this->dbh = new PDO($dsn, $credentials['privateUser'], $credentials['privatePassword'], $options);
}
}
}
// other database functions
}
?>
For a public connection (read/write), I simply used this:
$db = new Database('public', config['dbConfig']);
... or for a private connection (read-only), I used this:
$db = new Database('private', config['dbConfig']);
... and when I wanted to use the connection in another class, I simply injected the connection, like so:
$user = new User($db);
Works fine, but then I realised that I may need two connections inside that class, one for reading only and one for all. So I got a little confused, but had a go regardless. This is what I did:
Instead of calling the class with either of the connections, I called the class twice with both, like so:
$publicDB = new Database('public', $config['db']);
$privateDB = new Database('private', $config['db']);
and then injected both of those to my other class:
$user = new User($publicDB, $privateDB);
Inside this User class, this how I used the two connections:
<?php
class User {
private $dbh;
private $dbhp;
public function __construct($publicDatabase = NULL, $privateDatabase = NULL) {
$this->dbh = $publicDatabase;
$this->dbhp = $privateDatabase;
}
public function doSomething() {
$this->dbh->query("INSERT INTO......");
$this->dbh->execute();
}
public function doSomethingSafely() {
$this->dbhp->query("SELECT * FROM......");
$results = $this->dbhp->resultset();
}
}
?>
Right, this actually works fine but I'm worried it's not the acceptable method or it may cause problems later down the road. I have a few questions:
Is using two connections with different privileges still considered good practice? Even though I'm properly escaping and validating my data and binding the values using PDO?
If yes for above, is there a better way to manage the two connections for using in many classes or is what I have done acceptable?
I'm new learner in php OOP, I want to create a class function to get register users info, how can I do that?
class Functions{
public static function getUserInfo($user_id){
$sql = mysql_query("SELECT * FROM members WHERE user_id='".$user_id."'");
$rows = mysql_fetch_array($sql);
if(mysql_num_rows($sql) >= 1){
return $rows;
}
}
}
to echo user's info:
$user = new Functions();
$user->getUserInfo($_SESSION['user_id']);
echo $user->user_email;
I got nuthing output with 'undefined property' message, what is the proper way to create function to retrieve user's info? thanks.
Maybe that?
class Functions{
public static function getUserInfo($user_id){
if(empty($user_id)) {
return null;
}
// connect to db
$sql = mysql_query("SELECT * FROM members WHERE user_id='".$user_id."' LIMIT 1");
if(mysql_num_rows($sql) > 0){
$row = mysql_fetch_array($sql, MYSQL_ASSOC);
// close connection to db
return $row;
}
// close connection to db
return null;
}
}
$userID = !empty($_SESSION['user_id']) ? (int)$_SESSION['user_id'] : null;
$user = Functions::getUserInfo($userID);
if($user !== null) {
echo $user['user_email'];
}
This is ony example, use mysqli_* or PDO to manage data in database.
mysql_fetch_array returns array, not object.
$user['user_email'] should work.
In general as you mentioned OOP I would say your code is using classes, but it is not OOP (if I understand correctly how you're going to structure it). What you do is simply wrapping procedural code into a class.
With OOP you need to structure code such a way that it has self-contained objects, so creating "Functions" class containing various utility methods is generally a bad idea. Consider e.g. creating User object instead.
For database abstraction I would recommend checking PDO (http://www.php.net/manual/en/class.pdo.php).
I'm writing a WordPress plug-in and need to read the database name, username, and password (In order to do a sql dump). Is this possible?
Thanks-
Yes, they are defined in wp-config.php
Database Name: DB_NAME
Database User: DB_USER
Database password: DB_PASSWORD
Database Host: DB_HOST
They are define. See you wp-config.php in the root directory of Wordpress
Wordpress has some fairly goofy stuff going on throughout its OO code, this isn't the first one I've encountered as we dig deeper into the internals with each successive project at Moxune. See WP_User::__set doesn't persist custom fields as it claims.
The goofiness I refer to here of course is that something like the table prefix, aka wpdb::prefix is a public member variable, however things like dbname, dbpassword, and dbhost are protected and there are no public accessor methods.
I'm sure one of the Wordpress core devs will try to argue some rationale for it, but in the meantime may as well use some good 'ol OO to cope. My suggestion, a decorator.
class SaneDb
{
private $_oDb;
public function __construct(wpdb $oDb)
{
$this->_oDb = $oDb;
}
public function __get($sField)
{
if($sField != '_oDb')
return $this->_oDb->$sField;
}
public function __set($sField, $mValue)
{
if($sField != '_oDb')
$this->_oDb->$sField = $mValue;
}
public function __call($sMethod, array $aArgs)
{
return call_user_func_array(array($this->_oDb, $sMethod), $aArgs);
}
public function getDbName() { return $this->_oDb->dbname; }
public function getDbPass() { return $this->_oDb->dbpassword; }
public function getDbHost() { return $this->_oDb->dbhost; }
}
Then atop your plugin code (functions.php) setup a global in similar vein to wpdb.
global $sanedb;
$sanedb = new SaneDb($wpdb);
From there, just use $sanedb within your plugin instead of $wpdb.
Lastly, getting ahold of the database name et al.
$sanedb->getDbName();
This is super simple now. You can create a PHP file and use the following code.
$path = $_SERVER['DOCUMENT_ROOT'];
include_once $path . '/wp-config.php';
include_once $path . '/wp-load.php';
include_once $path . '/wp-includes/wp-db.php';
include_once $path . '/wp-includes/pluggable.php';
// We need the WordPress Database Credentials
global $wpdb;
$user = $wpdb->dbuser;
$pass = $wpdb->dbpassword;
$name = $wpdb->dbname;
If you need other data just do a print_r on the wpdb variable and you'll see everything inside of there.
I'm trying to create a PHP class extending mysqli that is capable of connecting with another user if the connection fails. It is probably easier to explain with code:
public function __construct() {
$users = new ArrayObject(self::$user);
$passwords = new ArrayObject(self::$pass);
$itUser = $users->getIterator();
$itPass = $passwords->getIterator();
parent::__construct(self::$host, $itUser->current(), $itPass->current(), self::$prefix.self::$db);
while($this->connect_errno && $itUser->valid()){
$itUser->next();
$itPass->next();
$this->change_user($itUser->current(), $itPass->current(), self::$prefix.self::$db);
}
if($this->connect_errno)
throw new Exception("Error", $this->connect_errno);
}
$user and $pass are static variables containing arrays of users and passwords.
If the first user fails to connect, I try with the next one.
The problem here is with $this->connect_errno. It says it cannot find Mysqli.
Is there any solution to this or should I create a Factory class?
Not sure why it doesn't find the object (hint, anybody?), however you can still use mysqli_error() for error handling, as shown in this article.
while(!mysqli_error($this) && $itUser->valid()) {
// (...)
}
and
if(mysqli_error($this)) {
throw new Exception(mysqli_error($this), mysqli_errno($this));
}
I have multiple functions, each running their own SQL query that needs to be inside a transaction... I'm using a static $link to save having to pass around links between functions... for example:
function db() {
$user = "username";
$pass = "password";
$db = "database";
$server = "localhost";
static $link;
if(is_null($link)){
$link = #mysql_connect( $server, $user, $pass );
}
mysql_select_db( $db, $link );
return $link;
}
function transactionWrapper($id){
$link = db();
# Start transaction
mysql_query("SET autocommit=0",$link);
# Get name from other function, but keep this function within the ACID transaction by using the same link
$name = getName($id);
mysql_query("UPDATE tbl2 SET name = '{$name}' WHERE id = '2'",$link);
# Commit transaction
mysql_query("COMMIT",$link);
}
function getName($id){
$link = db();
$result = mysql_query("SELECT name FROM user WHERE id = '{$id}'",$link);
return mysql_result($result,0,0);
}
This works brilliantly at the moment... I can have multiple function calls within different files and not have to pass around the $link.
The problem is now I want to do everything in an object for exception handling and I don't know how to replicate the same static variable upon multiple object instances...
I thought it would be something like:
class db{
static $link;
function db(){
# if link is null, create it with mysql_connect, otherwise return the link
}
}
The problem is... a static variable within a function stays alive for an entire page load, but the static link within an object only exists within the object right?
pconnect isn't an option either :P messy stuff
So how can I get around this? using Objects. I couldn't really find anything after googling for so long so I kind of get the impression I'm doing things a little differently to other people. Inside my transaction I have loads of function calls for various things.
I have alot of code as well... about a year of 60 hrs a week so I didn't have an entire application recode in mind! :P
Thanks, I hope someone can help me and I hope someone else stumbles upon this question in the future if it's answered!
If you declare your object at the start of your script (i.e, as a global), it should be alive for as long as your script runs. This is what my basic SQL class looks like:
class SQL_Connection {
var $connection;
function __construct() {
$this->connection = mysql_pconnect(DB_SERVER, DB_USER, DB_PASS) or die(mysql_error());
mysql_select_db(DB_TABLE, $this->connection) or die(mysql_error());
}
function query($query){
return mysql_query($query, $this->connection);
}
}
Then somewhere in you script you would do:
$db = new SQL_Connection;