Object and class structure for a larger project in PHP - php

Im about to start a large project in PHP. I want the code to be as clean as possible so I've started learning programming with classes & objects. Question is, is this the right way to structure it?
What I was thinking is three main classes. do, get and general
In general i will have a function for connecting to database.
In do i will store all functions that is inserting or updating the database for example:
class do
{
function createUser($name){
// Do stuff to create user
}
function like($id){
// Do stuff to like the id
}
}
$do = new do;
$do->like("52");
$do->createUser("Bob");
Question is, is this the right way to do this? Will this get sloppy when there are more than 20 functions in do or get?
Thanks in advance!

Remember that an object represents a thing, a noun (and a class is the type of thing); "do" is a verb, which is a pretty big clue that it's not a good choice for an object.
In fact, here, it's more like a namespace of "vaguely action-y functions", in contrast to the "get" namespace of "vaguely retrieval-y functions". Namespaces are cool too, but they should be static classes, or actual namespaces - you never need to refer to an "instance" of one, they just sit there.
As for "general", you should never, ever, plan a catch-all like that; it's like giving up on categorising your code before you started. You might end up with one later, for things you really can't put anywhere, but you should be really disappointed if you do.
The objects in the code you've mentioned here might be:
the database connection
a user
whatever thing it is that $id represents
Note that last one: an "ID" is not a thing either, it's an identifier for finding a particular thing.
In $do->like("52");, neither $do nor "52" have any real meaning. But if "52" is the ID of a page, and a user is doing the liking, a (very simple) OO implementation might look like this:
$page = Page::getByID("52");
$current_user->like( $page );
Or perhaps:
$page = Page::getByID("52");
$page->addLike( $current_user );
Immediately, the code is more readable, and relationships between your objects become clear. And that is why OOP is such a popular paradigm for organising code.
I've stuck to the basics here to get the main idea across; a modern OOP framework would go a lot further than this in turning things into objects; for instance:
"factories" and "repositories" allow creating and loading/saving objects without that static getByID call
a db connection object would be passed into objects that needed it, rather than them assuming they can create their own, which is known as "dependency injection"

I'd say, as a personal preference, that classes and objects are a great way to go. However, you're probably going to want to change "do" and "get" into "changes" and "retrievals" or something equally meaningful to you. Using keywords as class names is considered a really evil practice.

Related

OOP implementation doubts

I was starting a project today and after designing the database structure and how the data would be stored etc, I started the implementation. I am doing this on php, but the language isn't really relevant here, since my doubts are more architectured related or I guess, since I'm struggling more than I thought by implenting stuff in OOP on PHP. (Recently jumped on php, I've been coding in c++ and java before).
So, I started by creating my "User" class, simple as that, few attributes, and __construct, insert, update and delete methods. Those last 3, queries to the db.
Then this doubt came to my head, and I probably know the answer myself but I just don't find out.
I can now create instances and create new Users: $user = new User("John", 34) but, what if I want to edit the user "Dave"? Or I want to show all users. That method, for example, getAllUsers() which would return all users where would be implemented? Because it doesn't really belong to the class User does it? If it did, then how I would instance that method if I don't have any User instance?
I guess, I would need a class Users, or UserCollection which would be a collection of all the users, with the methods ´getCertainUser(id)´ and ´getAllUsers()´ which would return certain User or All of them, now then I would have a User I would be able to edit, right?
That being said, my questions is, how this problem should be addressed as the way to go, Am I complicating things too much? How this should be solved 'the correct way' in OOP. The times I've handled similar problems I've never used a database, so having a collection of users was the only way to store them, but having the database which stores the users feels redundant to have that collection of users.
Thanks in advance.
First, you are doing the right thing, by challenging yourself.
Obviously, there are many ways of doing things.
I highly believe that trying to keep concerns separated as much as possible and keeping classes small and simple are always two good guidelines when you want to write code that is easy to maintain and to test.
This would be one way of doing it :
To handle Models & Structures
Entity/User (Define the properties of a user)
Collection/User (implements ArrayIterator, just a structure)
To handle communication with your repository (db).
Repository/Mysql/User (implements getAllUsers, saveUser, deleteUser, etc.)
Those classes should implements common interfaces or inherit common abstract classes (if they share common logic).
For the basic persistency operation (update, delete, create), I have a little preference of moving them in the repository class instead of the entity. I prefer to avoid using "smart" entity objects. In my mind, it makes more sense. But, there are plenty of people who would disagree (and there is really no right or wrong here).
I have a Data Model structure similar to yours, where classes represent their table counterparts. In the case of retrieving multiple of a "User" or "Categories", etc, I have a static method inside the class, that returns instances of the class. In example:
class User{
public static function fetchUsersForBusiness(Business $business){
//fetch code here into variable $users from database...
$userObjs = [];
foreach($users as $userData){
$userObjs[] = new User($userData);
}
return $userObjs;
}
}
class Business{
}
The following code would return all the users that fit a certain criteria (in this case, a business they're associated with). I then return them as the objects themselves.
I've found this model to be fairly successful, and have used it in a multitude of languages including Java, PHP, and Swift. Hope it helps you.

Run parent non-static function from singleton child's instance property

I honestly think I did a pretty awesome job at creating the most exhaustive title possible :D.
I have a class Db that extends MySQLi. I have some stuff going on before executing queries, but to execute a query I need to call parent::query(). The problem is that Db is singleton and I don't really know how to do that..
$result = parent::query($sql);
This is what works if __construct is public. As soon as I make it private I start getting a bunch of errors basically saying
Couldn't fetch db
In a desperate attempt I tried this, which didn't work
$result = self::$instance::parent::query($sql)
Can someone please tell me how I can do this?
You've done a good job with the title, however I choked at "I have a class Db that extends MySQLi". I've already explained in some detail why this is a terrible idea here so please don't, then you don't ever have to worry about this issue.
What's even more troubling is that you're trying to create a singleton child, out of a non-singleton parent. This indeed requires a private (or at least protected) constructor, but because the parent's constructor is public you can't have an overriding constructor that employs a more strict access modifier. This is a breach of contract and goes agains all rules/conventions and widely accepted "good" practices
Read about the SOLID principles, please
Another issue with your snippet is one of ambiguity:
self::$instance::parent::query($sql);
Now, within the child class, it may seem logical, and a valid use of the parent keyword, but let's add this one line:
self::$instance = new OtherClass();
self::$instance::parent::query($sql);
In this case parent might be a class constant (they're only upper-case by convention, it's not a requirement!). PHP not being strong typed, you can't just assume the given variable will always be of the same type, now can you?
If you want the query method to be readily available to you on the child class, then just don't override it:
$evil = Db::getInstance($constructor_args);
$evil->query();//defaults to parent::query, if it's not overriden in the child class.
As an asside:
You shouldn't use a singleton in PHP
No, really, Honestly and truthfuly. Don't. Again, I've been quite verbose on that matter, too. Read my answer there please. It explains why you shouldn't use a singleton.
Besides, in your case, owing to my passionate loathing of the singleton pattern in PHP, I'd just create my own instance of PDO or MySQLi, thus bypassing your singleton-child-class, and set about making my life easier, and my code more testable anyway. Stop what you're doing: it's a waste of time!
Singletons are just globals in drag in PHP, because they are (by the very nature of the language) incapable of holding state in between requests. If you don't want 2 instances, don't create a second instance in the first place.
Singletons and gay marriage have something in common, in a weird way:
If you don't like gay marriage, that's your problem, not theirs. How can you avoid their marrying affect you? Two options:
prohibit them from marrying (absolute, imperative approach, dictatorship-style)
Don't marry a gay person (personal responsibility, live and let live, flexible-style)
Same applies to singletons: If you don't want there to be more than 1 connection to the DB, 2 options:
Create a singleton (absolute, imperative approach, dictatorship-style)
Don't connect to the DB a second time (personal responsibility, flexible)
Which of the two options seems the most reasonable?
Note: In case the analogy I made above offended anyone: That wasn't my intention, I simply tried to make a point.
As an asside (and waaay off-topic): if the preferable approach to both questions is, in your opinion, not the same in both cases, feel free to think that, that's your prerogative, but feel free to keep that to yourself, too. :)

How to use one object in another class : PHP framework

This is my current system for a framework that I'm making:
I create an object upon a request to access a non-existing property, that has the name of an existing class through the __get function defined in the Core class. The Core class extends every class.
So it works like this:
class Someclass extends Core
{
public function classmethod()
{
$this->otherclass->method();
}
}
This works exactly how I want it to work. However, I have no idea (after a lot of frustration) how to edit/create properties of the object, using this system.
So something like this would't work.
$this->view->somevar = "newvalue"; // this doesn't work.
I guess it has to do something with the __set function, but I failed to find out.
I received the following suggestions how to tackle this problem:
Dependency injection, Namespaces, Singleton pattern.
I would love to see how to implement what I'm trying to do using one of these patterns.
I have no idea which to choose in order to achieve my simple problem: Use objects in other classes, so i don't need to put anything into __construct's parameters or using global variables.
I am using __autoload.
I hope i can tackle this problem with your help.
First of all, the architecture you're attempting is extremly bad. Aparently you are using "magic" to create objects attached as properties to other objects. Which is bad, because if you use _get/_set, you will end up in problems sooner rather than later. Also extending from a common parent is a bad thing because it generates huge inheritance trees, and it allows most of the objects to have more than one responsability.
Before starting a framework, you might want to look over: SOLID
Now coming back to your question, if you use __get for getting a value, you can as well use __set for setting a value.
__construct method is there in order to allow you to initialize the object with all the data it needs in order to fulfill his sole purpose. Avoiding the __construct is kinda stupid, and defeats the purpose. You might want to pay attention to the D in SOLID in order to see what Dependency Inversion really is and to understand it.
Using __set loses completely the ability to typehint interfaces and so on. Therefore the code can become really buggy and ijcredibly hard to follow, since the flow is not so well defined, and the allocation is done in the back via magic. Also i can come up with 1 million other reason for which the architecture you are trying to use is wrong, but i will leave that for another time.

beginning OOP question about classes using classes

I'm trying to replace a site written procedurally with a nice set of classes as a learning exercise.
So far, I've created a record class that basically holds one line in the database's main table.
I also created a loader class which can:
loadAllFromUser($username)
loadAllFromDate($date)
loadAllFromGame($game)
These methods grab all the valid rows from the database, pack each row into a record, and stick all the records into an array.
But what if I want to just work with one record? I took a stab at that and ended up with code that was nearly identical to my procedural original.
I also wasn't sure where that one record would go. Does my loader class have a protected record property?
I'm somewhat confused.
EDIT - also, where would I put something like the HTML template for outputting a record to the site? does that go in the record class, in the loader, or in a 3rd class?
I recommend looking into using something like Doctrine for abstracting your db-to-object stuff, other than for learning purposes.
That said, there are many ways to model this type of thing, but in general it seems like the libraries (home-grown or not) that handle it tend to move towards having, at a high level:
A class that represents an object that is mapped to the db
A class that represents the way in which that object is mapped to the db
A class that represents methods for retrieving objects from the db
Think about the different tasks that need done, and try to encapsulate them cleanly. The Law of Demeter is useful to keep in mind, but don't get too bogged down with trying to grok everything in object-oriented design theory right this moment -- it can be much more useful to think, design, code, and see where weaknesses in your designs lie yourself.
For your "work with one record, but without duplicating a bunch of code" problem, perhaps something like having your loadAllFromUser methods actually be methods that call a private method that takes (for instance) a parameter that is the number of records to be retrieved, where if that parameter is null it retrieves all the records.
You can take that a step further, and implement __call on your loader class. Assuming it can know or find out about the fields that you want to load by, you can construct the parameters to a function that does the loading programatically -- look at the common parts of your functions, see what differs, and see if you can find a way to make those different parts into function parameters, or something else that allows you to avoid repetition.
MVC is worth reading up on wrt your second question. At the least, I would probably want to have that in a separate class that expects to be passed a record to render. The record probably shouldn't care about how it's represented in html, the thing that makes markup for a record shouldn't care about how the record is gotten. In general, you probably want to try to make things as standalone as possible.
It's not an easy thing to get used to, and most of "getting good" at this sort of design is a matter of practice. For actual functionality, tests can help a lot -- say you're writing your loader class, and you know that if you call loadAllFromUser($me) that you should get an array of three specific records with your dataset (even if it's a dataset used for testing only), if you have something you can run which would call that on your loader and check for the right results, it can help you know that your code is at least right from the standpoint of behavior, if not from design -- and when you change the design you can ensure that it still behaves correctly. PHPUnit seems to be the most popular tool for this in php-land.
Hopefully this points you in a useful group of directions instead of just being confusing :) Good luck, and godspeed.
You can encapsulate the unique parts of loadAllFrom... and loadOneFrom... within utility methods:
private function loadAll($tableName) {
// fetch all records from tableName
}
private function loadOne($tableName) {
// fetch one record from tableName
}
and then you won't see so much duplication:
public function loadAllFromUser() {
return $this->loadAll("user");
}
public function loadOneFromUser() {
return $this->loadOne("user");
}
If you like, you can break it down further like so:
private function load($tableName, $all = true) {
// return all or one record from tableName
// default is all
}
you can then replace all of those methods with calls such as:
$allUsers = $loader->load("users");
$date = $loader->load("date", false);
You could check the arguments coming into your method and decide from there.
$args = func_get_args();
if(count($args) > 1)
{
//do something
}
else // do something else
Something simple liek this could work. Or you could make two seperate methods inside your class for handling each type of request much like #karim's example. Whichever works best for what you would like to do.
Hopefully I understand what you are asking though.
To answer your edit:
Typically you will want to create a view class. This will be responsible for handling the HTML output of the data. It is good practice to keep these separate. The best way to do this is by injecting your 'data class' object directly into the view class like such:
class HTMLview
{
private $data;
public function __construct(Loader $_data)
{
$this->data = $_data;
}
}
And then continue with the output now that this class holds your processed database information.
It's entirely possible and plausible that your record class can have a utility method attached to itself that knows how to load a single record, given that you provide it a piece of identifying information (such as its ID, for example).
The pattern I have been using is that an object can know how to load itself, and also provides static methods to perform "loadAll" actions, returning an array of those objects to the calling code.
So, I'm going through a lot of this myself with a small open source web app I develop as well, I wrote most of it in a crunch procedurally because it's how I knew to make a working (heh, yeah) application in the shortest amount of time - and now I'm going back through and implementing heavy OOP and MVC architecture.

What is the best way to pass or access other objects in other classes in PHP?

I need some help in planning out how to do my classes in PHP. I have a session class and a database class that I pretty much need to access inside of every other class I use (forums, mail, users, lots more classes)
So I am looking for how I should access the session class inside of my other classes, 1 option is to make it GLOBAL, another is to pass $session and $database objects into every class I use like this...
$mail = new Mail($session, $database);
but this seems pretty tedious if I have to do it for 15+ different classes? Is there a better way?
Below is an example of some methods from my sessions class that I would be calling inside of other classes.
// set a value into session
$session->set('auto_id', 'some value for auto_id');
// get a value from session
$session->get('auto_id');
For scenarios like this i would make use of the registry pattern. This is a pretty good explanation.
The registry pattern acts like a storage for objects.
A code example is on it's way.
Edit:
In your example (new Mail($session, $database)), i think you should do this even if you use the registry pattern. This makes every thing less coupled and easier to understand and change parts independently. As I have not done so much PHP in the last couple of years, i don't know if there is any IOC-framework available, but that would help you instantiating your classes.
I'd have thought the singleton pattern would be a very good fit in this instance.
There's a nice simple tutorial (with some sample code) over at talkPHP that seems like a reasonable implementation.
For things like sessions and databases, I think global variables are fine here.
I disagree completely with using globals. I would either use the Registry pattern as suggested or make both the Session and DB themselves Singletons, although this will make unit testing much more difficult.

Categories