Right place to put query in OOP application - php

I want to build a simple blog application with PHP using OOP concept. So basically I have a Blog class and a Database Class. In Blog class I have a method called "createANewBlog()" which takes a blog text, and a database connection. for example:
class Blog{
public $id;
public $text;
public function createANewBlog($inText, $db)
{
$this->text = $inText;
$this->id = $db->create($inText);
return true;
}
}
so basically this function call a create() function in database class to get the last inserted Id.
class DB{
function create($intext){
$sql = "INSERT INTO....... ";
then i will send the last inserted id;
}
}
In the index controller I will simply create a blog object and call that method to create a new object.
Now my question is "Is it the right way to code in OOP" or I sould call the Query inside the blog class createANewBlog() function like:
createANewBlog($inText, $db){
$this->text = $inText;
$this->id = $db->execute("INSERT INTO .....");
return true;
}
please help me as I have no idea where is the right place to put the query(Inside the blog class or inside the databse class).

Your structure is some what right but the best practice is to isolate each thing according to their work.
So there would be following things.
Model (Blog class)
Database Connection class
Blog DAO Class
Controller
View
DAO (data access object) is an object that provides an abstract
interface to database.
So always use DAO to make communication between your model and database. It may contain insert, read, delete, find, filter methods/functions.
Uses of the above things are as follow,
Model should contain fields/properties of entity with Getter and setter methods.
Database connection class should contain only methods/logic to connect to database.
DAO class should contain all the logic of database operations.
Controller should have pipeline between views/models/DAOs.
View should contain only code to render the data without writing business logic in it.
This way you will keep it simple,robust and maintainable.

The idea of OOP is to create great application structure. In great application you need to use modular technique. i'll not giving you some big chunk of information which you need to follow . I'll rather giving you a tactics that i followed while i was learning OOP for the first time .
Let me give you an example with code!:
You're working with a database connection , so create a class that will store all the database connection and other connection stuff.
In here i created class called connection_admin
Class connection_admin {
protected $_link;
//If You Delete This Everybody of the Team Will send you a serial killer to kill you ......... :v :v
function __construct($host,$user,$pass,$db){
$this->_link = mysqli_connect($host,$user,$pass);
mysqli_select_db($db,$this->_link);
}
public function query($sql){
$result = mysqli_query($sql);
$this->confirm_query($sql);
return $result;
}
public function confirm_query($sql){
if (!$sql) {
# code...
die('Query Failed'. mysql_error());
}
}
public function count_matched_id($queried_output){
return mysqli_result($queried_output, 0);
}
}
Then i created a global object like "init.php" , which i'll include everywhere in my project.
<?php
include 'function/admin_connection.php';
$Connection = new connection_admin('localhost','root','','my_cart');
And now it's time to require them all in all .php files..
Then in the view files you just need to call $Connection->query() to query database
THADAAAAA!!
Note: it's not a very good use of php's OOP feature , but it'll teach
you how to use OOP . after that try to follow MVC structure.

Related

OOP PHP Can't get new mysqli from other class

I have class, where i make connection to database and do some queries.
But i can't make query to this database from other class. Problem is that class Cd can't see db connection command -> can't make a query. Here is the code:
require_once('config.php');
class myClass
{
public $mysqli;
public $res;
function connect()
{
$database = new Database();
$this->mysqli = new mysqli($database->db_host, $database->db_user, $database->db_pass, $database->db_table);
}
function cd($id)
{
......
}
}
}
class Cd extends myClass
{
function cdname($id)
{
$get= new Scandiweb();
$get->mysqli;
$this->res = $get->mysqli->query("SELECT * FROM disk WHERE id=" . $id . "");
if ($this->res->num_rows > 0) {
.........
}
}
}
Your code is a bit messy, so it's hard to tell where exactly the problem lies:
Why do you require config?
Why do you create a Database (which is more like a DbConfig) in the constructor instead of passing it?
What is the Scandiweb-class?
Why do you call mysqli->query on that class instead of $this
The last one is your immediate mistake. You extend myClass which creates the mysqli-connection and stores it as class variable $this->mysqli. That means that the child class Cd will have access to it. When you extend a class you can call all it's public and protected properties and methods. Only those marked as private can't be accessed.
That means instead of accessing $get->mysqli->query(...) you can do $this->mysqli->query(...). What would make sense in OOP is to create a connection once (like you do in the constructor) and pass it around to the services requiring a database connection. This is called Dependency Inversion Principle and using a Dependency Container makes it easier (but is not mandatory).
There are so called design patterns that will make it easier to deal with performing sql queries like in your code above. The most common ones are the Active Record-pattern as used in Laravel's Eloquent and the Propel library, the Table Data Gateway-pattern as used in Zend Framework's DB-component and the Data Mapper-pattern as employed by Doctrine ORM. If you want to write OOP code you should look at their documentation and maybe use one of those instead of dealing with everything yourself.

Composition vs Inheritance. What should I use for my database interaction library?

Consider a Database interaction module written in PHP that contains classes for interacting with the database. I have not started coding the class so I won't be able to give code snippets.
There will be one class per database table as explained below.
User - A class for interacting with the user table. The class contains functions such as createUser, updateUser, etc.
Locations - A class for interacting with the locations table. The class contains functions such as searchLocation, createLocation, updateLocation, etc.
In addition, I am thinking of creating another class as follows: -
DatabaseHelper : A class that will have a member that represents the connection to the database. This class will contain the lower level methods for executing SQL queries such as executeQuery(query,parameters), executeUpdate(query,parameters) and so on.
At this point, I have two options to use the DatabaseHelper class in other classes : -
The User and Locations class will extend the DatabaseHelper class so that they can use the inherited executeQuery and executeUpdate methods in DatabaseHelper. In this case, DatabaseHelper will ensure that there is only one instance of the connection to the database at any given time.
The DatabaseHelper class will be injected in the User and Locations class through a Container class that will make User and Location instances. In this case, the Container will make sure that there is only one instance of DatabaseHelper in the application at any given time.
These are the two approaches that quickly come to my mind. I want to know which approach to go with. It is possible that both these approaches are not good enough, in which case, I want to know any other approach that I can go with to implement the database interaction module.
Edit:
Note that the Container class will contain a static member of type DatabaseHelper. It will contain a private static getDatabaseHelper() function that will return an existing DatabaseHelper instance or create a new DatabaseHelper instance if one does not exists in which case, it will populate the connection object in DatabaseHelper. The Container will also contain static methods called makeUser and makeLocation that will inject the DatabaseHelper into User and Locations respectively.
After reading a few answers, I realize that the initial question has almost been answered. But there is still a doubt that needs to be clarified before I can accept the final answer which is as follows.
What to do when I have multiple databases to connect to rather than a single database. How does the DatabaseHelper class incorporate this and how does the container inject appropriate database dependencies in the User and Location objects?
Lets answer your questions from top to bottom, and see what I can add to what you say.
There will be one class per database table as explained below.
User - A class for interacting with the user table. The class contains functions such as createUser, updateUser, etc.
Locations - A class for interacting with the locations table. The class contains functions >such as searchLocation, createLocation, updateLocation, etc.
Essentially you have to choices here. The method you described is called the active record pattern. The object itself knows how and where it is stored. For simple objects that interact with a database to create / read / update / delete, this pattern is really usefull.
If the database operations become more extensive and less simple to understand, it is often a good choice to go with a data mapper (eg. this implementation). This is a second object that handles all the database interactions, while the object itself (eg. User or Location) only handles operations that are specific to that object (eg. login or goToLocation). If you ever want to chance the storage of your objects, you will only have to create a new data mapper. Your object won't even know that something changed in the implementation. This enforces encapsulation and seperation of concerns.
There are other options, but these two are the most used ways to implement database interactions.
In addition, I am thinking of creating another class as follows: -
DatabaseHelper : A class that will have a static member that represents the connection to the database. This class will contain the lower level methods for executing SQL queries such as executeQuery(query,parameters), executeUpdate(query,parameters) and so on.
What you are describing here sounds like a singleton. Normally this isn't really a good design choice. Are you really, really certain that there will never be a second database? Probably not, so you should not confine yourself to an implementation that only allowes for one database connection. Instead of making a DatabaseHelper with static members, you can better create a Database object with some methods that allow you to connect, disconnect, execute a query, etc. This way you can reuse it if you ever need a second connection.
At this point, I have two options to use the DatabaseHelper class in other classes : -
The User and Locations class will extend the DatabaseHelper class so that they can use the inherited executeQuery and executeUpdate methods in DatabaseHelper. In this case, DatabaseHelper will ensure that there is only one instance of the connection to the database at any given time.
The DatabaseHelper class will be injected in the User and Locations class through a Container class that will make User and Location instances. In this case, the Container will make sure that there is only one instance of DatabaseHelper in the application at any given time.
These are the two approaches that quickly come to my mind. I want to know which approach to go with. It is possible that both these approaches are not good enough, in which case, I want to know any other approach that I can go with to implement the database interaction module.
The first option isn't really viable. If you read the description of inheritance, you will see that inheritance is normally used to create a subtype of an existing object. An User is not a subtype of a DatabaseHelper, nor is a location. A MysqlDatabase would be a subtype of a Database, or a Admin would be a subtype of an User. I would advise against this option, as it isn't following the best practices of object oriented programming.
The second option is better. If you choose to use the active record method, you should indeed inject the Database into the User and Location objects. This should of course be done by some third object that handles all these kind of interactions. You will probably want to take a look at dependency injection and inversion of control.
Otherwise, if you choose the data mapper method, you should inject the Database into the data mapper. This way it is still possible to use several databases, while seperating all your concerns.
For more information about the active record pattern and the data mapper pattern, I would advise you to get the Patterns of Enterprise Application Architecture book of Martin Fowler. It is full of these kind of patterns and much, much more!
I hope this helps (and sorry if there are some really bad English sentences in there, I'm not a native speaker!).
== EDIT ==
Using the active record pattern of data mapper pattern also helps in testing your code (like Aurel said). If you seperate all peaces of code to do just one thing, it will be easier to check that it is really doing this one thing. By using PHPUnit (or some other testing framework) to check that your code is properly working, you can be pretty sure that no bugs will be present in each of your code units. If you mix up the concerns (like when you choose option 1 of your choices), this will be a whole lot harder. Things get pretty mixed up, and you will soon get a big bunch of spaghetti code.
== EDIT2 ==
An example of the active record pattern (that is pretty lazy, and not really active):
class Controller {
public function main() {
$database = new Database('host', 'username', 'password');
$database->selectDatabase('database');
$user = new User($database);
$user->name = 'Test';
$user->insert();
$otherUser = new User($database, 5);
$otherUser->delete();
}
}
class Database {
protected $connection = null;
public function __construct($host, $username, $password) {
// Connect to database and set $this->connection
}
public function selectDatabase($database) {
// Set the database on the current connection
}
public function execute($query) {
// Execute the given query
}
}
class User {
protected $database = null;
protected $id = 0;
protected $name = '';
// Add database on creation and get the user with the given id
public function __construct($database, $id = 0) {
$this->database = $database;
if ($id != 0) {
$this->load($id);
}
}
// Get the user with the given ID
public function load($id) {
$sql = 'SELECT * FROM users WHERE id = ' . $this->database->escape($id);
$result = $this->database->execute($sql);
$this->id = $result['id'];
$this->name = $result['name'];
}
// Insert this user into the database
public function insert() {
$sql = 'INSERT INTO users (name) VALUES ("' . $this->database->escape($this->name) . '")';
$this->database->execute($sql);
}
// Update this user
public function update() {
$sql = 'UPDATE users SET name = "' . $this->database->escape($this->name) . '" WHERE id = ' . $this->database->escape($this->id);
$this->database->execute($sql);
}
// Delete this user
public function delete() {
$sql = 'DELETE FROM users WHERE id = ' . $this->database->escape($this->id);
$this->database->execute($sql);
}
// Other method of this user
public function login() {}
public function logout() {}
}
And an example of the data mapper pattern:
class Controller {
public function main() {
$database = new Database('host', 'username', 'password');
$database->selectDatabase('database');
$userMapper = new UserMapper($database);
$user = $userMapper->get(0);
$user->name = 'Test';
$userMapper->insert($user);
$otherUser = UserMapper(5);
$userMapper->delete($otherUser);
}
}
class Database {
protected $connection = null;
public function __construct($host, $username, $password) {
// Connect to database and set $this->connection
}
public function selectDatabase($database) {
// Set the database on the current connection
}
public function execute($query) {
// Execute the given query
}
}
class UserMapper {
protected $database = null;
// Add database on creation
public function __construct($database) {
$this->database = $database;
}
// Get the user with the given ID
public function get($id) {
$user = new User();
if ($id != 0) {
$sql = 'SELECT * FROM users WHERE id = ' . $this->database->escape($id);
$result = $this->database->execute($sql);
$user->id = $result['id'];
$user->name = $result['name'];
}
return $user;
}
// Insert the given user
public function insert($user) {
$sql = 'INSERT INTO users (name) VALUES ("' . $this->database->escape($user->name) . '")';
$this->database->execute($sql);
}
// Update the given user
public function update($user) {
$sql = 'UPDATE users SET name = "' . $this->database->escape($user->name) . '" WHERE id = ' . $this->database->escape($user->id);
$this->database->execute($sql);
}
// Delete the given user
public function delete($user) {
$sql = 'DELETE FROM users WHERE id = ' . $this->database->escape($user->id);
$this->database->execute($sql);
}
}
class User {
public $id = 0;
public $name = '';
// Other method of this user
public function login() {}
public function logout() {}
}
== EDIT 3: after edit by bot ==
Note that the Container class will contain a static member of type DatabaseHelper. It will contain a private static getDatabaseHelper() function that will return an existing DatabaseHelper instance or create a new DatabaseHelper instance if one does not exists in which case, it will populate the connection object in DatabaseHelper. The Container will also contain static methods called makeUser and makeLocation that will inject the DatabaseHelper into User and Locations respectively.
After reading a few answers, I realize that the initial question has almost been answered. But there is still a doubt that needs to be clarified before I can accept the final answer which is as follows.
What to do when I have multiple databases to connect to rather than a single database. How does the DatabaseHelper class incorporate this and how does the container inject appropriate database dependencies in the User and Location objects?
I think there is no need for any static property, nor does the Container need those makeUser of makeLocation methods. Lets assume that you have some entry point of your application, in which you create a class that will control all flow in your application. You seem to call it a container, I prefer to call it a controller. After all, it controls what happens in your application.
$controller = new Controller();
The controller will have to know what database it has to load, and if there is one single database or multiple ones. For example, one database contains the user data, anonther database contains the location data. If the active record User from above and a similar Location class are given, then the controller might look as follows:
class Controller {
protected $databases = array();
public function __construct() {
$this->database['first_db'] = new Database('first_host', 'first_username', 'first_password');
$this->database['first_db']->selectDatabase('first_database');
$this->database['second_db'] = new Database('second_host', 'second_username', 'second_password');
$this->database['second_db']->selectDatabase('second_database');
}
public function showUserAndLocation() {
$user = new User($this->databases['first_database'], 3);
$location = $user->getLocation($this->databases['second_database']);
echo 'User ' . $user->name . ' is at location ' . $location->name;
}
public function showLocation() {
$location = new Location($this->database['second_database'], 5);
echo 'The location ' . $location->name . ' is ' . $location->description;
}
}
Probably it would be good to move all the echo's to a View class or something. If you have multiple controller classes, it might pay off to have a different entrypoint that creates all databases and pushes them in the controller. You could for example call this a front controller or an entry controller.
Does this answer you open questions?
I would go with the dependancy injection, for the following reason: if at some point you want to write tests for your applications, it will allow you to replace the DatabaseHelper instance by a stub class, implementing the same interface but that do not really access a database. This will make it really easier to test your model functionalities.
By the way, for this to be really useful, your other classes (User, Locations) should depend on a DatabaseHelperInterface rather than directly on DatabaseHelper. (This is required to be able to switch implementations)
The question of Dependency Injection vs. Inheritance, at least in your specific example comes down to the following: "is a" or "has a".
Is class foo a type of class bar? Is it a bar? If so, maybe inheritance is the way to go.
Does class foo use an object of class bar? You're now in dependency injection territory.
In your case, your data access objects (in my code approach these are UserDAO and LocationDAO) are NOT types of database helpers. You would not use a UserDAO, for instance, to provide database access to another DAO class. Instead, you USE the features of a database helper in your DAO classes. Now, this doesn't mean that technically you could not achieve what you want to do by extending the database helper classes. But I think it would be a bad design, and would cause trouble down the road as your design evolves.
Another way to think about it is, is ALL of your data going to come from the database? What if, somewhere down the road, you want to pull some location data from, say, an RSS feed. You have your LocationDAO essentially defining your interface -- your "contract", so to speak -- as to how the rest of your application obtains location data. But if you had extended DatabaseHelper to implement your LocationDAO, you'd now be stuck. There'd be no way to have your LocationDAO use a different data source. If, however, DatabaseHelper and your RSSHelper both had a common interface, you could plug the RSSHelper right into your DAO and LocationDAO doesn't even have to change at all. *
If you had made LocationDAO a type of DatabaseHandler, changing the data source would require changing the type of LocationDAO. This means that not only does LocationDAO have to change, but all your code that uses LocationDAO has to change. If you had injected a datasource into your DAO classes from the start, then the LocationDAO interface would remain the same, regardless of the datasource.
(* Just a theoretical example. There'd be a lot more work to get a DatabaseHelper and RSSHelper to have a similar interface.)
What you are describing with your User and Location classes is called a Table Data Gateway:
An object that acts as a Gateway to a database table. One instance handles all the rows in the table.
In general, you want to favor Composition over Inheritance and programm towards an interface. While it may seem like more effort to assemble your objects, doing it will benefit maintenance and the ability to change the program in the long run (and we all know change is the only ever constant in a project).
The most obvious benefit of using Dependency Injection here is when you want to unit test the Gateways. You cannot easily mock away the connection to the database when using inheritance. This means you will always have to have a database connection for these tests. Using Depedency Injection allows you to mock that connection and just test the Gateways interact correctly with the Database Helper.
Even though the other answers here are very good, I wanted to throw in some other thoughts from my experiences using CakePHP (an MVC framework). Basically, I will just show you a leaf or two out of their API; mainly because - to me - it seems well defined and thought out (probably because I use it daily).
class DATABASE_CONFIG { // define various database connection details here (default/test/externalapi/etc) }
// Data access layer
class DataSource extends Object { // base for all places where data comes from (DB/CSV/SOAP/etc) }
// - Database
class DboSource extends DataSource { // base for all DB-specific datasources (find/count/query/etc) }
class Mysql extends DboSource { // MySQL DB-specific datasource }
// - Web service
class SoapSource extends DataSource { // web services, etc don't extend DboSource }
class AcmeApi extends SoapSource { // some non-standard SOAP API to wrestle with, etc }
// Business logic layer
class Model extends Object { // inject a datasource (definitions are in DATABASE_CONFIG) }
// - Your models
class User extends Model { // createUser, updateUser (can influence datasource injected above) }
class Location extends Model { // searchLocation, createLocation, updateLocation (same as above) }
// Flow control layer
class Controller extends Object { // web browser controls: render view, redirect, error404, etc }
// - Your controllers
class UsersController extends Controller { // inject the User model here, implement CRUD, this is where your URLs map to (eg. /users/view/123) }
class LocationsController extends Controller { // more CRUD, eg. $this->Location->search() }
// Presentation layer
class View extends Object { // load php template, insert data, wrap in design }
// - Non-HTML output
class XmlView extends View { // expose data as XML }
class JsonView extends View { // expose data as JSON }
Dependency Injection is preferred if you have different types of services, and one service want to use other.
Your classes User and Locations sounds more like DAO (DataAccessObject) layer, that interact with database, So for your given case you should be using In Inheritance. Inheritance can be done by extending class or implementing Interfaces
public interface DatabaseHelperInterface {
public executeQuery(....);
}
public class DatabaseHelperImpl implemnets DatabaseHelperInterface {
public executeQuery(....) {
//some code
}
public Class UserDaoInterface extends DatabaseHelperInterface {
public createUser(....);
}
public Class UserDaoImpl extends DatabaseHelperImpl {
public createUser(....) {
executeQuery(create user query);
}
In this way your database design and code will be separate.

How to access the database class in OOP?

So I know that questions with 'what is the best' in their title aren't supposed to be asked, but really.. how should you do this?
We have a database class and, for example, a user class. A user class will get methods such as create() and update(), which will need to do database stuff.
As far as I know there are 2 main options, passing on the database object in every __construct() or make the database class static.
(Any other tips about OOP + database driven websites are also appreciated)
A very common pattern here is to make the database class a singleton construct, which is then passed to every object constructor (that is called Dependency Injection).
The purpose of making the database object a singleton is to ensure that only one connection is made per page load. If you need multiple connections for some reason, you would want to do it a different way. It's important to pass it via the constructors though, rather than creating the database object inside an unrelated class so that you can more easily test and debug your code.
// Basic singleton pattern for DB class
class DB
{
// Connection is a static property
private static $connection;
// Constructor is a private method so the class can't be directly instantiated with `new`
private function __construct() {}
// A private connect() method connects to your database and returns the connection object/resource
private static function connect() {
// use PDO, or MySQLi
$conn = new mysqli(...);
// Error checking, etc
return $conn;
}
// Static method retrieves existing connection or creates a new one if it doesn't exist
// via the connect() method
public static function get_connection() {
if (!self::$connection) {
self::$connection = self::connect();
// This could even call new mysqli() or new PDO() directly and skip the connect() method
// self::$connection = new mysqli(...);
}
return self::$connection;
}
}
class Other_Class
{
// accepts a DB in constructor
public function __construct($database) {
//stuff
}
}
// Database is created by calling the static method get_connetion()
$db = DB::get_connection();
$otherclass = new Other_Class($db);
// Later, to retrieve the connection again, if you don't use the variable $db
// calling DB::get_connection() returns the same connection as before since it already exists
$otherclass2 = new Other_Class(DB::get_connection());
Another method is to create your database class directly extending either mysqli or PDO. In that case, the __construct() method supplies the object to getConnect(), as in
public static function get_connection() {
if (!self::$connection) {
self::$connection = new self(/* params to constructor */);
}
return self::$connection;
}
Well, what you can do is to have the database access layer in one object, which is then passed to your objects, respecting the inversion of control pattern.
If you want to dig a bit into this direction, have a look into dependency injection (DI): http://en.wikipedia.org/wiki/Dependency_injection
Having a singleton is usually a bad idea as you will end up having problems when testing your code.
Having the database access logic within a model class such as User violates the separation of concerns principle. Usually DAO (Data Access Object) handles db related concerns.
There are ORM frameworks such as Hibernate, which handle mismatch between OO and relational models quite well, potentially saving a lot of manual work.
I'm really surprised that no one said this, but here it goes: ORM.
If your weapon of choice is PHP, then the major options are Propel and Doctrine. They both have many strengths and some weaknesses, but there's no doubt that they're powerfull. Just an example, from Propel's (my personal favourite) user manual:
// retrieve a record from a database
$book = BookQuery::create()->findPK(123);
// modify. Don't worry about escaping
$book->setName('Don\'t be Hax0red!');
// persist the modification to the database
$book->save();
$books = BookQuery::create() // retrieve all books...
->filterByPublishYear(2009) // ... published in 2009
->orderByTitle() // ... ordered by title
->joinWith('Book.Author') // ... with their author
->find();
foreach($books as $book) {
echo $book->getAuthor()->getFullName();
}
You won't get more OO than that!
They will handle a lot of things for you like for one, abstracting your data from the database vendor. That said, you should be able to move (relatively painlessly) from MySQL to SQL Server and if you're building your own tools for web applications, then beign able to adapt to different environments is a very important thing.
Hope I can help!
Hey have a look at ORM's. Let them do the hard work for you? fluent nhibernate or microsofts entity framework.
I could be misunderstanding your question. Sorry if so

PHP OOP: how to use a generic MySQL class in other classes

I've just started using OOP PHP and ran into a question. I've set up a generic mysql class that allows me to connect to a database and has some functions to obtain records from a table:
class mysql{
//some lines to connect, followed by:
public function get_record($sql)
{
$result = mysql_result(mysql_query($sql));
return $result;
//obiously it's a bit more advanced, but you get the picture.
}
}
Next, I have a class to obtain user details:
class user{
__construct($id)
{
$this->id = $id
}
public function get_username($id)
{
$username = get_record("SELECT name FROM users WHERE id = '".$this->id."'");
return $username;
}
}
I tried this, but got the error that the function get_record was unkown. I solved this by adding $mysql = new mysql(); to the user class.
However, it feels quite inefficient to have to instantiate the mysql object for every class that uses my database methods (that's pretty much all of them).
Is there a way to make the mysql class and its methods accessible to all other classes, without having to call the mysql class in every method?
For one, you don't need to use singleton in this case - or actually, you almost never do. See this article, for example.
Second, I think your OO designs are a bit off. The main point of object-oriented programming and design is to isolate responsibility into separate classes. Right now, you're giving your User class two main responsibilities - store / carry one user's relevant data, and query the data service (in this case, a simple MySQL / database abstraction layer).
You should first move that functionality into a separate object. Usually, this is called a Service - so in this case, it's a UserService. A UserService has one responsibility: provide access to User objects. So it'd sorta look like this:
class UserService {
public function __construct($mysql); // uses the mysql object to access the db.
public function get($id) {
$result = $this->mysql->get_record("select x from y");
$user = new User($result['id'], $result['name']); // assuming user has a constructor that takes an id and a name
return $user;
}
public function save($user);
public function delete($user);
}
You tie it all together at the start of your request (or where you need to access users):
$mysql = new MySQL($credentials);
$service = new UserService($mysql);
$user = $service->find(1337);
It's not perfect, but it's a much neater design. Your MySQL object does what it needs to do (build a connection, execute queries), your user object is plain dumb, and your service does only one thing, i.e. provide a layer between the actual storage layer and the thing calling it.
Design your mysql class to be called statically:
$username = Mysql::get_record("SELECT name FROM users WHERE id = '".$this->id."'");
http://php.net/manual/en/language.oop5.static.php
This is a common problem, and so there is a common solution to this.
As you might know, in software development common solutions on common problems are called Design Patterns.
There are two design patterns that can help you solve this problem.
In a more abstract sense the problem you are facing is:
How can i make class A available in class B?
The Singleton pattern
"In the singleton pattern a class can distribute one instance of itself to other classes."
This is not exactly what you are looking for, as your website may use multiple database connections. However, it is used by a lot of people in this way.
Read some information about using a singleton class as a database provider here:
https://www.ibm.com/developerworks/library/os-php-designptrns/#N10124
More information on the singleton pattern in PHP:
http://www.fluffycat.com/PHP-Design-Patterns/Singleton/
Another sensible approach is the registry pattern:
Registry Pattern
You can find information about the registry pattern on the link below, as well as an implementation almost identical that you are looking for:
http://www.sitecrafting.com/blog/php-patterns-part/
Even more powerful is a combination between the singleton and the registry.
Good luck and enjoy learning OOP PHP!
You should pass in the mysql object to each user object. So it would look like this:
$mysql = new mysql();
$user = new user( $mysql, $id);
$name = $user->get_username();
class user {
public function __construct($mysql, $id) {
$this->mysql = $mysql;
$this->id = $id;
}
public function get_username() {
$username = $this->mysql->get_record("SELECT name FROM users WHERE id = '".$this->id."'");
return $username;
}
}
using global variables, although that is probably not the best option.
$mysql = new mysql();
function someFunction() {
global $mysql;
$mysql->get_record(...)
}
or a static method for your mysql class (see Singleton)
class mysql {
public static $theInstance = new mysql();
public static function getInstance() {
return $this->theInstance;
}
}
function someFunction() {
$database= mysql::getInstance();
$database->get_record(...)
}
Start to think to use Doctrine, it's better
http://www.doctrine-project.org/

Is a general class necessary for a site PHP site?

I have a CORE class that pertains only to my specific site, ie, it performs site specific functions. I have a database class (for mysql), and other classes like access, validator, upload, template etc etc... I know that php classes can only extend one class each, so almost all of my classes extend the database class. I was looking over a public twitter class used on the twitter API. In it, there are functions to do almost everything you could do by going directly to the website, insert, delete, whatever... Should I put all site relatie functions inside my Core class and keep it out of the general scope of my scripts. Right now I have something like this....
Heres an example, as of right now I have functions like
$core = new Core();
$core->get_user_info($user_id);
$core->get_user_articles($user_id);
Inside that function, i perform database queries to select the needed information so i dont have to do it directly since it can get messy.
I also have functions to delete things, like
$core->Delete_Article($article_id);
However, I dont have functions to insert. Instead I use the Database class directly to add information, like so.
$article = array(user_id => $_SESSION['user_id'], body => $_POST['body']);
$db = new Database();
$db->Insert($article, 'articles');
or
$user = array(name => $_POST['name'], email => $_POST['email']);
$db->Insert($user, 'users');
Now, in the topic of separation of one aspect from another, should I put ALL of my database select/insert/update/delete queries inside my general CORE class and do ALL the database actions in the background
Like instead of $db->Insert(), i could use $core->insert_user() or just continue as I'm doing.
This is a pretty common mistake for people new to object-oriented programming. You don't want to extend a class just because it has some functions that you need. In fact, you may want to avoid extending classes at all while you're getting started. Although most intros to OOP make a big deal out of inheritance, I would steer clear for the moment.
Instead, think of how you can group together functions in terms of the way they're used. For example, say you're managing users. You need to keep track of user information, add users, delete them, etc. You could create classes like this:
class User {
function getName()...
function getID()...
}
class UserAdmin {
function addUser(User $user)...
function getUser($id)...
function deleteUser($id)...
}
These classes are organized according to concepts, not according to what functions you need to call.
When you do need reusable functions for things like database access, you'll generally want another separate object doing the work. So instead of having your UserAdmin class extend a Database class to format its SQL:
// wrong
class UserAdmin extends Database {
function getUser($id) {
$this->openConnection();
$this->runQuery("select * from users where id = {1}", $id);
}
}
... you can just use the Database class from within your UserAdmin class:
// right
class UserAdmin {
function getUser($id) {
$db = new Database();
$db->openConnection();
$db->runQuery("select * from users where id = {1}", $id);
}
}
class Database {
function openConnection() ...
function runQuery() ...
}
Initially it will seem like more work, but it keeps your various classes independent. That makes them easier to write, maintain, and test.
Because PHP is reloading everything on each page view, I do not see much advantage to instanciating classes for everything. If you break the functionality up into files that are roughly coorspond to your database schema, you can scale up and up without adding more and more functions that are loaded on each page hit.
It matters when you have dozens or hundreds of tables / classes.
Specifically for PHP, we prefer this style:
class Member
{
public static function Insert($aData)
{
//Insert member and return ID
}
public static function Select($Member_ID)
{
//select member and return Array
}
public static function List($aFilter)
{
//Return list of members filtered by specific criteria
}
}
To take it one step further, we have a static class App which holds relevant "singletonish" variables.
class App
{
public static $DB = NULL;
}
App::$DB = new Connection();
Now, anywhere in your app, you can say:
App::$DB->Query(...);
Generally, what I do is add a simple query() method to my database class which just takes SQL is an argument. Then I abstract all my general CRUD methods to the specific class. so if you have an Article class, the the deleteArticle() method would go in that class, and would extend the Article class with the database class. use $db->query($sql) within that class. and so on with your other classes...

Categories