Work with database in classes - php

I´m wondering how to work with database in classes. For example how to write queries for easy future edit and by OOP rules.
First example:
class User {
public function select($query) {
//work with data
return $data;
}
public function insert($query) {
//work with data
}
}
In this example user (me) add queries for each method. For me, big disadvantage is that I must remember correct form of my query. This example is easy to understand, but in case I will work with more complex queries, it would hard to write correct form of query.
Next example:
class User {
const select = "SELECT * FROM user WHERE ID = ?";
const insert = "INSERT INTO user VALUES (?)";
public function select($id) {
//work with data
return $data;
}
public function insert($id) {
//work with data
}
}
I defined each query as contstant. This form of class is very handy but on the other hand if I want to get ID of user I can't, because I would know name of ID field in the database. This problem I solve in third example
Third example:
class User {
private $table, $idField;
public function setDatabaseInformation($table, $idField) {
$this->table = $table;
$this->idField = $idField;
}
public function select($id) {
//work with data
//query as SELECT * FROM $this->table WHERE $this->idField = ?
return $data;
}
public function insert($id) {
//query as INSERT INTO $this->table VALUES (?)";
//work with data
}
}
Personaly I think, this example is the best, because there I have everything what I want and I can't rememeber forms of queries. On the other hand, this example is a bit longer, very universal and I don't know it is correct by OOP rules.
My questions are: Is there any other options how to write queries in database? Is the last example correct by OOP rules? Which way do you use?
Thanks for suggestions.

Abstract the whole thing inside the class! You want to write code which looks like this in the end:
$database = new PDO(...); // or whatever
$userStorage = new UserStorage($database);
$user = $userStorage->getById(42);
$users = $userStorage->getByName('Joe');
class UserStorage {
protected $db;
public function __construct(PDO $db) {
$this->db = $db;
}
public function getById($id) {
$stmt = $this->db->prepare('SELECT ... WHERE id = ?');
$stmt->execute([$id]);
...
return $user;
}
...
}
You only want to write each logical query once in one specific, authoritative place. For each possible logical "action", create a method (one method to get users by id, one to get them by name, etc.). Each method can be as complex or simple as necessary internally, but it is the one place where you write the specific query to get the specific data. Lastly: dependency inject your database connection.

Related

Is there a problem using a "shared" private property in a class to build fluent/evolving DB query?

I'm trying to write a class that relies on some legacy code to fetch data from database related to a particular table (productcode)
For not repeating myself, I implement a private property $sql that holds the "evolving" query and finally applying getResult() on it (as this snippet shows it)
My question: is there any design principle violation by implementing this pattern? (specially adopting the "shared" $sql property). If the answer is yes, why and what is the proper way to do it?
<?php
class ProductCodeDataSource
{
use dbmanager_aware_trait;
private $sql;
public function findByProductId($productId)
{
$this->sql = [];
$this->sql['fields'] = 'productcode_value';
$this->sql['tables'] = 'productcode';
$this->sql['where'][] = sprintf('productcode_product_id = %d', (int) $productId);
$this->sql['order'][] = 'productcode_default';
return $this;
}
public function findOneByProductId($productId)
{
$this->findByProductId($productId);
$this->sql['limit'] = 1;
return $this;
}
public function getResult()
{
// get_all_value is a legacy method that fetches data from mysql DB
// build_select_ext is also a legacy method that builds sql queries from
// $sql array structures
return$this->dbmanager->get_all_value($db->build_select_ext($this->sql));
}
}

SQL query efficiency when using PHP classes

I've been programming in PHP for many years, however only recently started programming with classes. I have the following - basic - user class as follows:
<?php
/* The class for constructing any user's information
*/
class User {
protected $userId, $email, $userGroup;
protected function getEmail() {
return $this->email;
}
protected function getUserId() {
return $this->userId;
}
protected function getUserGroup() {
return $this->userId;
}
public function __construct($userId='') {
if($userId) {
$select = mysql_query("SELECT userId, email, user_group FROM user WHERE userId = '$userId'");
while($user==mysql_fetch_array($select)) {
$this->email = $user[email];
$this->userId = $userId;
$this->userGroup = $user[user_group];
}
}
}
}?>
So I understand I can do the following
<?php
$user = new User($userId);
echo $user->getEmail();
?>
To display the user's email address for a given userId. What I'd like to know is, what would be the best way - using OOP - to display, say, 40 user's emails. Obviously creating 40 user objects would be silly as that's 40 SQL queries. Would you simply make a "users" class that was used for returning an array of multiple users, after doing an SQL given various parameters?
Ie
<?php
$getUsers = new Users('Tom');
// create 'Users' object where name is 'Tom'
print_r($users);
// prints the returned array of users?
?>
Thanks for your help. Hopefully this is clear.
I'd do it something like this (using another class):
class UserRepository {
public function getByName($name) {
$result = mysql_query("SELECT userId, email, user_group FROM user WHERE name = '$name'");
$users = [];
while ($row = mysql_fetch_assoc($result)) {
$user = new User;
$user->email = $row['email'];
$user->userId = $row['userId'];
$user->userGroup = $row['user_group'];
$users[] = $user;
}
return $users;
}
}
Addition:
The following example gives a good idea on how you can make the classes more testable and easy to modify in the future should they need to be:
UserRepositoryInterface
interface UserRepositoryInterface {
public function getByName($name);
public function getByUserId($id);
}
MySqliUserRepository
class MySqliUserRepository implements UserRepositoryInterface {
public function getByName($name) {
// Get by name using mysqli methods here
}
public function getByUserId($id) {
// Get by user id using mysqli methods here
}
}
PDOUserRepository
class PDOUserRepository implements UserRepositoryInterface {
public function getByName($name) {
// Get by name using PDO methods here
}
public function getByUserId($id) {
// Get by user id using PDO methods here
}
}
Usage
class Foo {
protected $userRepository;
public function __construct(UserRepositoryInterface $userRepository) {
$this->userRepository = $userRepository;
}
public function bar() {
$user = $this->userRepository->getByUserId(10);
}
}
Regarding use of mysql_
It may not be exactly how you do it but it'll give you an idea. Also mysql_ is depreciated so its best to use mysqli_ or PDO (my personal recommendation). PDO is also much more OOP friendly.
PDO: http://php.net/manual/en/book.pdo.php
mysqli_: http://php.net/manual/en/book.mysqli.php
Update:
Your individual user class would simply contain information relating to the user. The user class shouldn't contain any way to retrieve a user, that is the job of the repository. So if you want to retrieve 1 user, instead of doing in the User __construct as you currently do, add a method to the UserRepository that looks something like this:
public function getByUserId($id) {
// Select user from db, check only 1 exists, make user object, return.
}
I try to separate my data objects from the DB stuff. In your case, I'd make the following arrangements:
An instance of the User class represents an individual user, either in DB or not. The constructor does not retrieve anything from DB, it just populates class properties.
For users not in DB (e.g., a newly created user) the userId property is NULL (not '').
Methods that do DB stuff expect a database interface (or at least an object) as argument:
public function save(PDO $pdo){
}
There're static methods to fetch stuff from DB where a class instance does not make sense yet; they return either a User instance or a User collection:
public static function fetchById(PDO $pdo, $id){
}
public static function fetchAll(PDO $pdo){
}
When it makes sense, I write a private method to share common code:
private static function fetch(PDO $pdo, array $filter=array()){
$sql = 'SELECT id, email, group
FROM user' . PHP_EOL;
$params = array();
if( isset($filter['id']) ){
$sql .= 'WHERE id=:id';
$params['id'] = $filter['id'];
}
//...
}
public static function fetchById(PDO $pdo, $id){
$data = self::fetch($pdo, array('id' => $id));
if( empty($data) ){
return NULL;
}else{
reset($data);
return curren($data);
}
}
public static function fetchAll(PDO $pdo){
return self::fetch($pdo);
}
The User collection I've mentioned can as simple as an array of User instances, or as elaborate as your own generics implementation.
This way, a typical script looks like this:
// Fetch my details
$me = User::fetchById(1);
// Create a new user
$you = new User(NULL, 'Joe', 'Guests');
$you->save($pdo);
$message = sprintf('User created with ID=%d', $you->userId);
Instead of using the construct to retrieve a user, you could use methods to insert/retrieve users instead.
You can create methods to insert new users, update a particular user, retrieve one particular user or retrieve all (with conditions) in an array of users' objects, etc

How to best fetch data with pdo as a getter

I'm hoping you can shed some light to my questions guys. What I need is basically the best practise of getting and assigning properties from database rows (instance getter). It is a pretty standart issue and I have know how it works in C#, but I'm unclear how to accomplish similar results in php and havent found any solution online which covers my needs.
So lets assume I have this simplified code:
Class User{
private $Pdo;
private $UserID;
private $UserName;
function GetUserName(){
return $this->UserName;
}
function GetUserInfo(){
// return user object with given user id, in this example just use "1"
$Pdo = $this->Pdo;
$Query = $Pdo->query('select * from User where UserID = 1');
$Query->setFetchMode(PDO::FETCH_CLASS, "User", array($Pdo) ); // this is returning object
$UserInfo = $Query->fetch();
return $UserInfo;
}
}
Then when I wanted to get the user object I would call it like:
$User = new User($Pdo);
$UserInfo = $User->GetUserInfo();
echo $UserInfo->GetUserName();
This works, however I dont like to do it this way. One option would be to use static method so in the end I would end up with something like:
$UserInfo = User::GetUserInfo()
Which I suppose is called "Singleton" (edit: not a singleton:)) and is generally noted as bad practise.
My question is how it should look like? What I would like to have is this:
$UserInfo = new User($Pdo);
$UserInfo->GetUserInfo();
echo $UserInfo->GetUserName();
I know that in GetUserInfo method I can manually assign the values to current object ($this) such as:
function GetUserInfo(){
// get data from db
$this->UserName = "John"; // this value I will get from db
}
However I would like to use FetchClass so I can get all the properties based on their names in one line and not assign them manually. I hope that you understand what my issue is :) I would love to hear your opinions of what is the best way of doing this.
Thank you very much for any input.
One step in the direction to a best pratice and good design would be to separate your domain models and the persistence layer.
So you are independent of the used database or could even replace the database with a webservice for example. Look at the Data Mapper pattern.
So your User model would only consist of the properties + getters/setters and methods that use these properties in some way (business logic).
class User
{
protected $UserID;
protected $UserName;
public function getUserId()
{
return $this->UserID;
}
public function setUserId($userId)
{
$this->UserID = userId;
return $this;
}
...
}
Your mapper holds the database connection and is responsible for saving/fetching the User object.
class UserMapper
{
protected $_pdo;
public function __construct($pdo)
{
$this->_pdo = $pdo;
}
public function getUserById($id)
{
// TODO: better use prepared statements!
$query = $this->_pdo->query("select * from User where UserID = ".id);
$query->setFetchMode(PDO::FETCH_CLASS, "User");
return $query->fetch();
}
public function save(User $user)
{
// insert/update query
}
...
}
You can use it like:
$userMapper = new UserMapper($pdo);
$user = $userMapper->getUserById(1);
echo $user->getUserName();
$user->setUserName('Steve');
$userMapper->save($user);
There are other similar patterns like Table Gateway pattern. But I prefer the data mapper because of the independecy of the data source.
Look at the whole catalog from Martin Fowler: Catalog of Patterns of Enterprise Application Architecture
Another useful thread: What is the difference between the Data Mapper, Table Data Gateway (Gateway), Data Access Object (DAO) and Repository patterns?

What are other PHP class designs for DB object interactions?

I have a table called "User" that holds user info. I'll call my user class and create a user object so that I can grab whatever info is needed for that user.
I have been using the below classes and hybrids of them for my sites but have been never really happy with them mainly because I'm unsure how other developers handle this situation and if there is a better solution. Below are a few methods I have been using, I'm curious to see how other developers are doing.
Idea # 1
class User
{
//public user
public function __construct()
{
//get user - queries table and returns all fields in array
}
//get name function - references user array and returns name
//set name function - sets new name in array
//commit function - commits array to db (saves changes)
}
Idea # 2
class User
{
//user id
public function __construct(user id)
{
//set user id
}
//get name function - calls db directly and returns name
//set name function - calls db directly and sets name
//commit function - commits array to db saves changes
}
Idea #1 seems to be the most efficient, or least amount of DB calls but a little more complex and less straightforward than Idea #2.
I like idea #2 better but I'm afraid of it's scalability because each function makes a call to the DB.
Thoughts
I would recommend for you to learn about DataMapper pattern. The basic idea goes like this :
Lets say (for the sake of example ) that you have an MVC structure for application that deals with books.
It would make sense to have a model Library which is responsible with domain logic of managing different books.
The model deals with unknown number of Book instances ( many books in a library ). Each book :
knows everything about itself ( authors , publishing date , language .. etc.)
has no idea where it is stored or where the data come from
can be related to a table in Database , but contains information from multiple tables
And then you have an instance of BookMapper class, which :
model receives in the constructor ( implementing predefined interface )
knows how to ( and where ) store the Book objects , and how to read data into them
can be switched to a different object, if storage medium changes
if it works with DB, then it in constructor has already requested a DB object ( like PDO )
has methods store( Book $book ) and retrieve( Book $book ) for saving book's data , or getting new info from storage
This is how i would do it ..
What about something like:
class Db
{
function __construct()
{
$this->engine = DB_ENGINE;
$this->dbname = DB_NAME;
$this->host = DB_HOST;
$this->username = DB_USERNAME;
$this->password = DB_PASSWORD;
$this->connect();
}
function connect()
{
$this->db = new PDO($this->engine.':host='.$this->host.';dbname='.$this->dbname, $this->username, $this->password);
}
}
class Table extends Db
{
protected $from = null;
function __construct()
{
parent::__construct();
}
function select($columns, $where, $order, $offset, $limit)
{
}
function update($where, $data)
{
}
function delete($where)
{
}
etc...
}
class User extends Table
{
function __construct()
{
parent::__construct();
$this->from = 'blog';
}
function get_user()
{
$this->select(params);
}
function get_user_count()
{
}
etc...
}
This way you can easily use it to get other info as well just be creating a new class with it's functions to retrieve / delete / etc the info.
Firstly the user object is meant to hold user data, so i would suggest method #1, method #2 is more of a amodel object that send's commands to fetch data.
Now, you can automatically map user rows to an object in 1 single query, for example:
class User
{
//Predefine Here
public $id;
public $username;
public $password;
public $email;
public $hash;
public function profileLink()
{
return sprintf('%s',$this->id,$this->username);
}
}
//Fetch the results
$result = $sth->fetchAll(PDO::FETCH_CLASS, "User");
$userObjects = array();
foreach($result as $user)
{
$userObjects[] = $user;
}
//Now you can use like so:
echo $userObjects[2]->profileLink();
so my other answer here : PDO PHP Fetch Class
I think that if you are going to implement your own User class, then it should look something similar to the following:
class User {
private $UserID;
private $Username;
private $AvatarImg;
// ... First Name, Last Name, ALL other user information that you store in the DB.
function __construct( $uid ) {
// Populate all private members from the DB for the given user id.
}
function update( $assocArrayOfValues ) {
// Commit these values to the Db and Update the private members.
}
// All Associated get functions ( getName, getUID, getUsername etc )
// Any other specialty functions you may want, e.g...
function getAvatar() {
return "<img src = '" . $this->AvatarImg . "'/>";
}
}
What you are trying to archive is the functionally of an ORM (Object-Relational-Mapper). It may be beneficial to use one and not do it yourself.
If you want to do it on your own, I would go for lazy-loading. This is a bit in between your two ideas. In PHP it looks something like this:
class User
{
private $id; // depends on your application, could also be a string
private $dirty;
private $loaded;
private $properties;
public function __construct($user_id)
{
$this->id = $user_id;
}
public function __destruct()
{
if ($this->dirty) {
// commit to DB
}
}
public function __get($name)
{
if (!$loaded)
{
$this->loadFromDb();
}
// error-handling if the key does not exist is missing here!
return $this->properties[$name];
}
public function __set($name, $value)
{
// May be required to load the data here...
// error-handling if the key does not exist is missing here!
$properties[$name] = $value;
$this->dirty = true;
}
private function loadFromDb()
{
// query data from db and store it in properties
}
}
The advantage of this design is, that if you construct objects, which ultimately you don't need, nothing has touched the database yet. Also note the commit done during deconstruction.
If you load collections sometimes it may be useful to have a function load a bunch of rows from the DB and pass the rows as argument to a constructor when creating the objects. This would require only one query instead of possibly hundreds if you would have constructed each object by itself.
As a further enhancement you may provide a User::reset() function, which throws away all the changes made.
I would suggest you to use a PHP-Framework like Yii.
http://www.yiiframework.com/
It has nice Features to interact between Classes and your Database.
You can also get some inspiration there if you really want to do this on your own.

proper way to get all users using OOP

ive got a user class where i can get the name, date of birth etc of the user... (below)
class user {
private $id;
private $name;
private $dob;
private address;
function __construct($id) {
$this->id = $id
}
}
i was just wondering what the best practice to get all users. do i create a function to get an object of this class for each user found from the database? :s
From a purely OO perspective, the User shouldn't have knowledge of databases etc.
My first thoughts would be a UserFactory, which will talk to the database and know how to build User objects from SQL results. You may want to specialise this to have a SQLUserFactory, an XMLUserFactory etc.
It's worth reading about Factory patterns. Factories look after the creation of objects. In this scenario, you may want to later distinguish between different types of User objects. In this scenario it would be the Factory's responsibility to decide what sort of object to create, not the User's.
This looks like an attempt at Active Record. In php there are a few ORM implementations that include Active Record. I suggest looking into that.
Otherwise look into at PDO and binding query results to objects. You might be able to get something working that way.
Do you mean which class should have the responsibility for getting Users from the DB?
The User class seems wrong, why would an indivudual user "know" about queries to obtain all (or some) users.
You could have a UserHome or UserKeeper class. and in there have methods which return result sets of user.
Getting users from a database isn't an OOP question, it's a database question, and typically an SQL question. Unless I don't get what you mean?
Object models in this case are somewhat artificial because putting a load() or get() method on the user class doesn't make a lot of sense because you don't want to get 100 users with 100 separate database roundtrips/selects. It's an example of "leaky abstractions". Implementation matters.
So you're going to need to write a function to run a query, return a bunch of rows and turn them into user objects.
Or use an ActiveRecord-like abstraction (eg that used in CodeIgniter or Kohana) to a set of records by passing in a criteria or a set of records.
Assuming your users are stored in a MySQL database, I would create the following static method in Users. Well, I would probably use an ORM, like Doctrine instead, but...
static function queryAll() {
$query = "SELECT id,name,dob,address FROM user";
if ($result = $mysqli->query($query)) {
$all = array();
while ($obj = $result->fetch_object()) {
$all[$obj->id] = $obj;
}
$result->close();
return $all;
}
return array();
}
In my point of view Database interaction should be separate and put in model as of in zend framework and controlled from controller where you should make of object of model class and call fetch all function.
Is this is the right approach.
class User
{
public $id;
public $username;
public $password;
public function __construct()
{
$this->username = "";
$this->password = "";
}
}
separate database interactions to an interface
interface UserStore
{
public function Create(User $user) : User;
//public function GetById(string $id) : ?User;
public function getByUserName(string $userName) : ?User;
}
implement the interface.
class MySqlUserStore implements UserStore
{
public $db;
public function __construct($db)
{
$this->db = $db;
}
public function Create( User $user) : User
{
$query = "INSERT INTO users (username, password) VALUES (?, ?)";
$user->id = $this->db->insert($query, array($user->username, $user->password));
return $user;
}
public function getByUserName(string $userName) : ?User
{
$query = "SELECT * from users where username = ?";
$result = $this->db->select($query, array($userName));
if(count($result) > 0) {
$user = new User();
$user->id = $result[0]['id'];
$user->username = $result[0]['username'];
$user->password = $result[0]['password'];
return $user;
}
return null;
}
}
Use the user store
$userStore = new MySqlUserStore($this->db);
$user = $userStore->getByUserName($username);

Categories