new to oop in PHP a plea for clarifying concepts - php

I love the PHP language, Ive got SOME coding experience but I am fairly new to PHP although I have been learning a lot I feel I am now stuck / held back by not getting the hang of OOP concepts, although I have been browsing through multiple tutorials.
This is not so much a question about the code itself but rather behind the logic of it
Consider this tutorial I worked from
class person {
var $name;
function set_name($new_name) {
$this->name = $new_name;
}
function get_name() {
return $this->name
}
}
$stefan = new person();
$jimmy = new person;
$stefan->set_name("Stefan Mischook");
$jimmy->set_name("Nick Waddles");
echo "Stefan's full name: " . $stefan->get_name();
echo "Nick's full name: " . $jimmy->get_name(); ?>
I understand what is going on above and I understand the concept but I cant see the benefit of it, I just feel I could have created the above in a much simpler way by simply doing
function person($name){
return $name;
}
echo person("Tim Jones");
Why the getter and the setter function, why not just one function in class person?
Why go through all that code above when my function above is so much shorter?
Where is the benefit here?
I'm basically just looking for someone to give me a bit of clarification on the whole OOP concept which I cant seem to get by the many repetitive tutorials I have been reading.

A good case for using classes is when you may want to expand or rewrite functionality later on.
A few years back I wrote an application in PHP which was used to create issues within Jira. At this point, I was using SOAP to perform the actual issue creation and updates using the published API
Later on, within the same application, I needed to use features within Jira which were associated with the Atlassian Greenhopper/Agile extension. This extension used a REST API and it became apparent that Atlassian was moving all their APIs across to using REST
As I had used a class for the calls to Jira, all the actual grunt work in the background was abstracted. I knew which data was expected and what data I would be expecting
In the end, I wrote a new class to use REST (via cURL calls), and re-wrote the class which accessed Jira. I didn't have to go through the whole application and check each call to a Jira function as the data in and data out was the same.
In reality, the classes I wrote all descended from the REST class:
REST -> JIRA_BASE -> JIRA
The JIRA_BASE class contained methods which were common across all Jira projects (get project names, get user id's etc). The JIRA class itself contained a couple of functions (createJiraIssue and updateJiraIssue) which were particular to each Jira project
The other advantage of using classes and objects is that you can put place-holders in for functions. In the REST class, trying to use a DELETE method (rather than GET, POST or PUT) for a REST call would error straight away (I hadn't written it as I didn't need it). However, I have re-used the same class in another application where I did need to use the DELETE method so that is now written
It also became apparent that the new application needed a change in one aspect of functionality. This was implemented without re-writing any of the calling code
Getters and setters are used to ensure that data is accessed in a controlled manner. If you just use a variable within a script, any part of that script could alter the data. If that data is stored within a class and set to private, then only a call to the getter or setter can alter or retrieve that data.
Additionally, getters and setters can alter the way the data is actually stored but still present it in a usable format. For example, when performing a call to
$obj -> setName('DaveyBoy');
that data could be reversed, escaped, encrypted, stored in session variables, sent to a database and rot13'ed (in no particular order). But, a call to
$name = $obj -> getName()
would still store 'DaveyBoy' in $name without any intervening steps.
I've rambled about classes and why I use them but, hopefuly, this helps to explain a bit.

The advantages of OOP is that anything acting upon a class or object does not need to know how that class or object works under the hood, and much more complicated things can be accomplished in the background with the bulk of your application being un-involved, making your code much more readable.
Consider the following [partially]pseudocode web app example:
$users = array();
$users[] = new User('joe', ADMIN, ACTIVE);
$users[] = new User('jane', ADMIN, ACTIVE);
$users[] = new User('bill', USER, INACTIVE);
class User {
public $Name;
public $Security;
public $Active;
public function __construct($name, $security = USER, $active = INACTIVE) {
$this->Name = $name;
$this->Security = $security;
$this->Active = $active;
}
public function ToggleActive() {
//Not actual working code ahead
$this->Active = ($this->Active) ? INACTIVE : ACTIVE;
$sql->query('UPDATE users SET active=$this->Active WHERE name=$this->Name');
}
public function SetSecurity($security) {
//More non-functional examples
$this->Security = $security;
$sql->query('UPDATE users SET security=$this->Security WHERE name=$this->Name');
}
}
?>
<html>
<form>
<!-- this is, of course, the wrong markup, but the concept is there-->
foreach($users as $user) {
<name>$user->Name</name>
<security>$user->Security <button $user->SetSecurity(ADMIN)>Set Admin</button> <button $user->SetSecurity(User)>Set User</button>
<active>$user->Active <button $user->ToggleActive>Toggle Active</button>
}
<!-- you could even have the class itself output the form html with something like $user->DrawEntryHTML();-->
</form>
</html>
Obviously, there is a lot more that goes in to the web app interface of such an operation (AJAX, function handlers, etc.), but the basics are there, and only the user object itself needs to know how to perform the operation. The rest of your app can simply say Hey, user. You're active now.
OOP gives you an abstract but meaningful way of accomplishing what you want your application components to do. In most applications these days, when a user interacts, or a task happens, a number of things need to happen in order to store, display, and modify its elements. You also gain the advantage of only needing to change a small bit of code in your class in case of a change, update, or feature addition, rather than chasing all over the rest of your code for everything that relates to your users (in this case).
You'll find that a well-written OOP application has a very short program loop (or index.php), and the bulk of the work happens within its class objects.

Consider what happens when you want to change the behaviour of the code - suppose it's been running for a while and you discover that you have lots of duplicate records where people have used variants in the whitespace and capitals. You might then want to amend the code to....
function set_name($new_name) {
$new_name=trim(strtoupper($new_name));
$new_name=str_replace(' ',' ', $new_name);
$new_name=str_replace(' ',' ', $new_name);
$name_parts=explode(' ', $new_name);
$this->surname=array_pop($name_parts);
$this->forenames=implode(' ', $name_parts);
}
function get_name()
{
return $this->forenames . ' ' . $this->surname;
}
But you don't need to change any of the code which interacts with the object.
Now think about a class which describes organizations rather than individuals - they have names - but not forenames and surnames. If you have a class with the same interface (get_name, set_name) then you can throw a mixed bundle of person and organizations at your Christmas card printer application without having to amend the app to cope with the different data types.
(tutorial examples are kept very simple for a reason, unfortunately a lot of the benefits of OO only become apparent when dealing with complex problems - stick with it and you'll get there)

Notice that my answer focus not on the major strengths of OOP as you have already read on those and - as they currently don't apply to your situation - were meaningless. I'm going to focus on what OOP can do to you right now.
The example you give is actually a good one.
Say that you also wanted to attach height, weight, birthday and profession to a person.
Not using objects you could create an array of arrays (to store multiple persons with multiple attributes) but 2 hours into the coding you would try to access the persons job as:
echo $persons[0]['job'];
And it would fail as that field is actually named 'profession'; using objects not only will your IDE know the getters it will also help you.
The major strength of OOP is only really seen when you work in teams or expose code to be used by others however the example I gave should suffice to understand why even as a single developer there are benefits.
That being said, for over simplistic actions it can be overkill.

Related

OOP object models, best practice [duplicate]

I'm not new to PHP or programming at all. But recently I was thinking about website programming in PHP and how easier it was before the OOP. Anyway, I prefer OOP than the old procedural style.
I want to implement a website but it seems I always have to use a global or a static variables. And I'm starting to wonder, how can I do it without those?
Anyway, what I'm talking about is having a class for each "component" of the website.
For example if it was an url shortener website it would be: links, members, database.
What I'm talking about is way more complicated, at least 8 classes.
Anyway, my current approach is the following:
$database = new Database(...);
$links = new Links($db);
$users = new Users($db);
Anyway, for example I want to get all the links a user posted by its ID, I need to use both links and both users components.
Is there any other way I could do this? Any other approach? except passing them as constructor parameters.
You should have the following components:
Business objects, which model and express one particular "thing" in your app:
class Link { ... }
class User { ... }
These don't "do" anything, they're just there to formalise your data structures. These objects have getter and setter methods to get and set individual attributes, which are also validated there:
public function setUrl($url) {
if (!/* validate the URL here*/) {
throw new InvalidArgumentException("$url is not a valid URL");
}
$this->url = $url;
}
Minimum required data is part of the constructor. This ensures your data integrity application-wide. It allows you to assert that when you have an instance of Link, the data expressed by it is minimum valid data for a link.
A database link. Only the bare necessary thing to connect to a database, nothing more, nothing less. A raw PDO or mysqli object will do just fine.
A data-object mapper, which takes a database link and knows how to store business objects in the database and how to retrieve them:
class LinkStorage {
protected $db;
public function __construct(PDO $db) {
$this->db = $db;
}
}
This class has all the various methods of how to retrieve things from your database:
public function getById($id) {
$stmt = $this->db->prepare('SELECT ... FROM ... WHERE id = :id');
$stmt->execute(compact('id'));
if (!$data = $stmt->fetch()) {
throw new RuntimeException("Record with id $id does not exist");
}
return new Link($data['url']);
}
You can have all sorts of different queries encapsulated this way, e.g.:
/**
* Returns all links by a particular user.
* #param User $user
* #return Link[]
*/
public function getAllFromUser(User $user) {
...
}
The usage is then simple:
$db = new PDO(...);
$linkStorage = new LinkStorage($db);
$userStorage = new UserStorage($db);
$user = $userStorage->getById($id);
$links = $linkStorage->getAllFromUser($user);
This kind of code would then be encapsulated in a service class, which holds all the possible "actions" you can do in your app. registerUser(array $data), getLinksOfUser($id), newLinkFromPostData(array $data) etc.
What I've just described is basically the model portion of an MVC-style application. The other two parts would be controllers which call the service methods, and views which output data retrieved from service methods. This approach keeps responsibilities separate and isolated and allows you to put higher-level logic and functionality together like building blocks. Business objects are the lowest building block, their structure needs to be solid and well defined for the rest to work. Data-object mappers just concern themselves with putting those objects into the database and getting them back out again. Services then put all this together in various complex ways and make things happen.
You shouldn't have any cyclic dependencies with this, as responsibilities are well separated. Your individual dependencies may still be somewhat complex. If it becomes too cumbersome to instantiate classes, you'll want to look into Factories:
$factory = new Factory;
$userStorage = $factory->newUserStorage();
All the complexity of instantiation is encapsulated in this factory. One step further are dependency injection containers, who you can configure in, for example, an XML file to specify which class depends on what, and then the DI container will take care of it for you.
I was thinking about website programming in PHP and how easier it was
before the OOP
Well, stick to procedural then. If it is easier to write a well written website in a procedural or functional way then opposed to the ojbect-oriented way. Stick ti what you are used to. OO isn't better then functional. It's just a different approach.
the public void main() in php
In the lanuage Java every piece of software we write has a single entry point. The public void main() method. This method fires up the entire application and passes in the arguments provided on startup. It is also the only exit point in the application. the application ends in this method (unless it crashes).
In php, there is no single entry point. We have a bunch of files that run some scripts that do some more stuff and then somewhere along the line another script decides to return stuff and die();
Dependency injection and how IoC libraries can help
When using dependency injection, it becomes a real pain in the a$$ when creating objects and passing arround the correct instance of a class. We start solving this problem with ugly solutions: Singleton, globals, statics, ... Making our software more and more tightly coupled and harder to maintain.
Inversion of Control can help here. there are some really greate articles on the webz.
You can use autoloading in PHP for a better solution:
http://php.net/manual/en/language.oop5.autoload.php

Looking for a way to handle/approach PHP OOP websites

I'm not new to PHP or programming at all. But recently I was thinking about website programming in PHP and how easier it was before the OOP. Anyway, I prefer OOP than the old procedural style.
I want to implement a website but it seems I always have to use a global or a static variables. And I'm starting to wonder, how can I do it without those?
Anyway, what I'm talking about is having a class for each "component" of the website.
For example if it was an url shortener website it would be: links, members, database.
What I'm talking about is way more complicated, at least 8 classes.
Anyway, my current approach is the following:
$database = new Database(...);
$links = new Links($db);
$users = new Users($db);
Anyway, for example I want to get all the links a user posted by its ID, I need to use both links and both users components.
Is there any other way I could do this? Any other approach? except passing them as constructor parameters.
You should have the following components:
Business objects, which model and express one particular "thing" in your app:
class Link { ... }
class User { ... }
These don't "do" anything, they're just there to formalise your data structures. These objects have getter and setter methods to get and set individual attributes, which are also validated there:
public function setUrl($url) {
if (!/* validate the URL here*/) {
throw new InvalidArgumentException("$url is not a valid URL");
}
$this->url = $url;
}
Minimum required data is part of the constructor. This ensures your data integrity application-wide. It allows you to assert that when you have an instance of Link, the data expressed by it is minimum valid data for a link.
A database link. Only the bare necessary thing to connect to a database, nothing more, nothing less. A raw PDO or mysqli object will do just fine.
A data-object mapper, which takes a database link and knows how to store business objects in the database and how to retrieve them:
class LinkStorage {
protected $db;
public function __construct(PDO $db) {
$this->db = $db;
}
}
This class has all the various methods of how to retrieve things from your database:
public function getById($id) {
$stmt = $this->db->prepare('SELECT ... FROM ... WHERE id = :id');
$stmt->execute(compact('id'));
if (!$data = $stmt->fetch()) {
throw new RuntimeException("Record with id $id does not exist");
}
return new Link($data['url']);
}
You can have all sorts of different queries encapsulated this way, e.g.:
/**
* Returns all links by a particular user.
* #param User $user
* #return Link[]
*/
public function getAllFromUser(User $user) {
...
}
The usage is then simple:
$db = new PDO(...);
$linkStorage = new LinkStorage($db);
$userStorage = new UserStorage($db);
$user = $userStorage->getById($id);
$links = $linkStorage->getAllFromUser($user);
This kind of code would then be encapsulated in a service class, which holds all the possible "actions" you can do in your app. registerUser(array $data), getLinksOfUser($id), newLinkFromPostData(array $data) etc.
What I've just described is basically the model portion of an MVC-style application. The other two parts would be controllers which call the service methods, and views which output data retrieved from service methods. This approach keeps responsibilities separate and isolated and allows you to put higher-level logic and functionality together like building blocks. Business objects are the lowest building block, their structure needs to be solid and well defined for the rest to work. Data-object mappers just concern themselves with putting those objects into the database and getting them back out again. Services then put all this together in various complex ways and make things happen.
You shouldn't have any cyclic dependencies with this, as responsibilities are well separated. Your individual dependencies may still be somewhat complex. If it becomes too cumbersome to instantiate classes, you'll want to look into Factories:
$factory = new Factory;
$userStorage = $factory->newUserStorage();
All the complexity of instantiation is encapsulated in this factory. One step further are dependency injection containers, who you can configure in, for example, an XML file to specify which class depends on what, and then the DI container will take care of it for you.
I was thinking about website programming in PHP and how easier it was
before the OOP
Well, stick to procedural then. If it is easier to write a well written website in a procedural or functional way then opposed to the ojbect-oriented way. Stick ti what you are used to. OO isn't better then functional. It's just a different approach.
the public void main() in php
In the lanuage Java every piece of software we write has a single entry point. The public void main() method. This method fires up the entire application and passes in the arguments provided on startup. It is also the only exit point in the application. the application ends in this method (unless it crashes).
In php, there is no single entry point. We have a bunch of files that run some scripts that do some more stuff and then somewhere along the line another script decides to return stuff and die();
Dependency injection and how IoC libraries can help
When using dependency injection, it becomes a real pain in the a$$ when creating objects and passing arround the correct instance of a class. We start solving this problem with ugly solutions: Singleton, globals, statics, ... Making our software more and more tightly coupled and harder to maintain.
Inversion of Control can help here. there are some really greate articles on the webz.
You can use autoloading in PHP for a better solution:
http://php.net/manual/en/language.oop5.autoload.php

OOP concept understanding

I recently started learning the basics of OOP in PHP.
I am new to a whole lot of concepts.
In the traditional procedural way of doing things, if I had a repetitive task, I wrote a function and called it each time.
Since this seems to be a regular occurence, I created a small library of 5-10 functions, which I included in my procedural projects and used.
In OOP, what is the valid way of using your functions and having them accessible from all objects?
To make things closer to the real world, I created a thumbnail class, that takes an image filename as an argument and can perform some operations on it.
In procedural programming. when I had a function for creating thumbnails, I also had a function to create a random md5 string, check a given folder if said string existed, and repeat if it did, so I could generate a unique name for my thumbnails before saving them.
But if I wanted to generate another unique name for another purpose, say saving a text file, I could call that function again.
So, long story short, what is the valid OOP way to have the method randomise_and_check($filename) (and all other methods in my library) accessible from all the objects in my application?
Great question. The first thing you want to do is identify the primary objects you will be working with. An easy way to do this is to identify all the nouns related to your project. In your example it sounds like you will be working with images and strings, from this we can create two classes which will contain related attributes (functions, member variables, etc). And as you wisely mentioned, we need to ensure that the algorithms you are converting into OOP can be called from any context, so we try to keep them abstract as possible (within reason).
So for your specific situation I would suggest something like:
// Good object reference, abstract enough to cover any type of image
// But specific enough to provide semantic API calls
class Image
{
// Using your example, but to ensure you follow the DRY principle
// (Don't repeat yourself) this method should be broken up into two
// separate methods
public static function randomise_and_check($fileUri)
{
// Your code here
....
// Example of call to another class from within this class
$hash = String::generateHash();
}
}
// Very abstract, but allows this class to grow over time, by adding more
// string related methods
class String
{
public static function generateHash()
{
return md5(rand());
}
}
// Calling code example
$imageStats = Image::radomise_and_check($fileUri);
There are several other approaches and ideas that can be employed, such as whether or not to instantiate objects, or whether we should create a parent class from which we can extend, but these concepts will become evident over time and with practice. I think the code snippet provided should give you a good idea what you can do to make the jump from procedural to OOP. And, as always, don't forget to read the docs for more info.
-- Update --
Adding an OOP example:
class Image
{
protected $sourceUri;
public function setSourceUri($sourceUri)
{
$this->sourceUri = $sourceUri;
}
public function generateThumb()
{
return YourGenerator::resize($this->getSourceUri);
}
}
$image = new Image();
$image->setSourceUri($imageUri);
$thumbnail = $image->generateThumbnail();
The way I see it, you have two options:
Don't worry about cramming yourself into OOP and just make them standard, global functions in some utilities.php file you include wherever you want to use it. This is my preferred method.
If you take the more OOP approach, you could make them static functions ("methods") in some utilities class. From the PHP documentation:
<?php
class Foo {
public static function aStaticMethod() {
// ...
}
}
Foo::aStaticMethod();
$classname = 'Foo';
$classname::aStaticMethod(); // As of PHP 5.3.0
?>
Create an (abstract) Util-class with static functions:
example from my Util class:
abstract Class Util{
public static function dump($object){
echo '<pre class=\"dump\">' . print_r($object, true) . '</pre>';
}
}
How to use:
<?
$object = new Whatever();
//what's in the object?
Util::dump($object);
?>
For a beginner, OOP development is not all that different from procedural (once you master the basic concepts it gets quite a bit different, but that's not important to learning the basics).
You deal in OO concepts all the time, you just don't realize it. When you click on a file in your file manager, and manipulate that file.. you're using Object Oriented concepts. The file has attributes (size, type, read-only, etc..) and things you can do with it (open, copy, delete).
You just apply those concepts to development by creating objects that have properties and things you can do with it (methods).
In the OOP world, you don't typically make things available to everything else. OOP is all about "encapsulation", which is limiting access to only that which is needed. Why would you make a "haircut" method available to an orange juice object? You wouldn't. You only make the "haircut" method available to objects that need haircuts.
Writing reusable OO software is very difficult. Even professionals can't get it right a lot of the time. It requires a mixture of experience, training, practice, and frankly luck in some cases.
You should read about Dependency Injection as it seems to apply to your specific problem. Basically, you have an object that depends on some abstraction, maybe the "Image Library" functionality. In your controller, you would create an instance of the "Image Library" object and inject that dependency into whatever other objects required it.
That is, you need to stop thinking on the global scope altogether. Instead, you have to compartmentalize functionailties in a sane way and tie them together. Basically, objects should only know about as little as they need to know (also look up Law of Demeter and SOLID). I reiterate, this is tough to do correctly, and most of the time you can still have an application that works beautifully even if it's done incorrectly.
If you want to be very strict about this you should apply this line of thinking to everything, but if you have a function that wraps something very simple like return isset($_POST[$key]) ? $_POST[$key] : $default; I see no real harm in creating a global function for that. You could create an HttpPost wrapper class, but that is overkill in most circumstances IMO.
The short answer: use ordinary function. OOP encourages you to think about data and associated routines, using static functions instead of ordinary does not make your program more object-oriented. Following the single programming paradigm is not practical, combine them when you see that this will make your program cleaner.

CRUD and OOD. How to approach this?

Please be brutally honest, and tear my work apart if you have to.
So I'm re-writing a small web-application that I recently made. The reason for this is simply that the code got pretty messy and I want to learn and apply better OO design. What this application should do is just simple CRUD.
I have a database with 3 tables, companies and partners which are in no relation to each other and city which has a 1:n relation with companies and partners. Very simple, really. Now, I have several questions which i will state at the end of my post. Here i'll just try to explain:
My first approach was that I created classes company, partner and city, fetched all datasets from the database and created objects from that:
class company {
private $id = null;
private $name = null;
private $city = null;
//many more attributes
function __construct( $id, $name, $city, [...] ) {
$this->id = $id;
$this->name = $name;
$this->city = $city;
//huge constructor
}
/*
* getters + setters here
*
* no need to paste the partner class as it looks just like this one
*
*/
}
And that is all these classes did. I fetched every dataset from the database and constructed company, partner and city objects (the attribute city within these classes is an object with several attributes itself) and saved them into two arrays arr_companies and arr_partners, which then held these objects...and it worked fine like that.
Now, what I wanted is to update, insert, delete into the database, and all 3 classes (city, company, partner) need this functionality. My approach was that I created a new class with a constructor that would basically take 2 strings command and object, e.g. ('update', 'company') and it would then update the company directly in the database leaving my objects untouched. That made me really sad, because I had such nicely constructed objects and I didn't know how to make use of them.
Questions:
Is it bad to have such huge constructors (my biggest one would take
28 parameters)?
Should you have a separate class for database
operations or is it better to have maybe an abstract class or
interface for it and let the subclasses themselves handle update, delete, insert?
Is it common to just write, delete from the database whenever or should I just apply these changes to my objects and only execute the commands to the database later, for example when the session ends?
I figure an application like this must have been done a fantastillion times before. What is the proper approach here? create objects, work with objects, save them to the database?
I have so many questions but I think many of them I just don't know how to ask.
Please note that if possible I would not like to use an ORM at this point.
Thank you very much for your time.
Questions posed in OP:
"Is it bad to have such huge constructors (my biggest one would take 28 parameters)"?
Yes. Imagine the calling code. You would have to pass 28 different values, not to mention each call would have to respect the exact order specified in the constructor. If one parameter was out of place, you could wreck havoc with parameter dependent algorithms. If you really need to pass a large number of parameters, I would recommend passing them in as an array (posted an example to another SO question).
"Should you have a separate class for database operations or is it better to have maybe an abstract class or interface for it and let the subclasses themselves handle update, delete, insert?"
Generally speaking, when creating classes, you want to try to identify the nouns that best represent your business needs. In your specific case you would probably have three classes; Company, Partner, and City.
Now within each class (noun), your methods would be in the form of verbs, so symantically your calling code makes sense: if ($company->getName() === 'forbes')
As you mentioned, each class needs a database object (dbo) to work with, so you could implement any number of patterns to expose datase connections to your classes; singleton, singleton with factory, or dependency injection, etc.
Abstract (parent) classes are great for sharing common algorithms across child classes, and should be identified when you are in the psuedo-code stage of your design. Parent classes also allow you to force child classes to have methods by declaring abstract methods within the parent.
Interfaces are a useful tool in certain situations, but I find they are less flexible than declaring abstract methods in parent class. But are good in situations where classes do not share a common parent.
"Is it common to just write, delete from the database whenever or should I just apply these changes to my objects and only execute the commands to the database later, for example when the session ends"?
CRUD activity should happen at the time the action is executed. If you wait for the session to end, you may run into situations where a session is pre-maturely ended due to a user closing a browser, for example. To better protect your data you can wrap your CRUD activity within transactions.
If you are running a high-traffic application, you can implement a queuing system and queue up the work to be done.
"I figure an application like this must have been done a fantastillion times before. What is the proper approach here? create objects, work with objects, save them to the database"?
You are correct, this has been done before, and are commonly referred to as ORMs (object relation mappers). Basically, an ORM will introspect your database schema, and create objects (and relations) which represent your schema. So instead of working with native SQL, you are working with objects. Although you can use SQL for custom business needs, but in the case of Doctrine, you would use Doctrine Query Language (DQL) vs native SQL.
An ORM I would highly recommend is Doctrine.
If you do not want to use an ORM, you can add CRUD methods to your primary classes. I Opted for an interface so your classes don't have to extend from a parent comprised of database operations. Also, check out this post on using a singleton/factory for exposing your classes database object(s).
Consider the following:
// Company.php
class Company implements iDatabaseOperation
public function delete()
{
// Lets use a DBO singleton/factory for DB access
// Uses PDO, which is strongly recommended
$dbo = Database::factory(Database::DATABASE_NAME);
$dbo->beginTransaction();
try {
$sql =
"DELETE FROM " .
" company " .
"WHERE " .
" id = :companyId " .
"LIMIT 1";
$stmt = $dbo->prepare($sql);
$stmt->bindValue(':companyId', $this->getId());
$stmt->execute();
$dbo->commit();
} catch (Exception $e) {
$dbo->rollback();
error_log($e->getMessage();
$e = null; // Php's garbage collection sucks
}
}
}
// iDatabaseOperation.php
interface iDatabaseOperation
{
public function delete();
public function update();
public function insert();
}
It is realy bad. Code is completele unreadable in this case. You have options
to use setters (can add validation logic inside, better readability, no need to fill empty fields with null)
to have separate class builder for each domain class (takes some memory for additional object). Example in java hope you can understand:
class CompanyBuilder {
private final Company c;
public CompanyBuilder() {
c = new Company();
}
CompanyBuilder addId(String id){c.id = id;}
// id should be package visible and class should be located in the same package with builder
CompanyBuilder addName(String name){...}
CompanyBuilder addCity(String city){...}
Company build(){ return c;}
}
hybrid solution to have methods to organise chain(worse debugging, better readability). In java will be methods:
class Company {
...
Company addId(String id){
this.id = id;
return this;
}
Company addName(String name){...}
...
}
Usage:
Company c = new Company().addId("1").addName("Name1");
maybe you can create more granular objects to reuse them later and add specific logic in correct place. For instance it can be Address(Location) object for company.
Follow single responsibility principle. SOLID description on wiki.
It helps to change database specific code without affection of other part of system in your case. Well, separate domain and database specific code, have common interface or abstract class(if you have common logic for all of domain classes - liskov principle). In subclasses implement domain specific part.
If you do not want to lose data you should save them each time or have cluster of servers or have distributed cache. If it is ok to lose save them in the end of session as batch. It will increase youre performance. Also you should save in transaction each time if you have concurrent updates.
Approach is get data from database/construct objects from this data or new objects/ work(update) objects/write data from objects to database
just write more code and read stackoverflow
Finally I suggest to read "Clean Code: A Handbook of Agile Software Craftsmanship" R.Martin.
You are essentially writing your own ORM. So, I wouldn't discount just switching to one that's already been written for you. The advantage to rolling your own is that you gain an understanding of how it works as your write it. But the disadvantage is that someone else has probably already done it better. But assuming you want to continue on...
General Advice: Remember to always break the problem down into simpler and simpler pieces. Each class should only perform a simple function. Also, you should not have to worry about caching updates... unless perhaps your database is on the other end of a remote connection over a modem.
Specific Advice follows:
I would setup your entity instance classes to house data and not to do a lot of data loading. Use other classes and logic for loading the data. I would use the constructor of the entity class only to populate the data that pertains to the class (and it's children).
A simple thing to do is to use static methods on the entity class for loading and saving data. E.g.
class city {
private $id = null;
private $name = null;
function __construct( $id, $name ) {
$this->id = $id;
$this->name = $name;
}
// getters and setters
...
// ---------------------
// static functions
// ---------------------
public static function loadById($cityId) {
// pull up the city by id
$retval = new city(row["id"], row["name"]);
// close db connection
return $retval;
}
public static function loadByCustomerId($customerId) {
// pull up multiple cities by customer id
// loop through each row and make a new city object
// return a hash or array of cities
}
public static function update($city) {
// generate your update statement with $city->values
}
// other methods for inserting and deleting cities
...
}
So now the code to get and update cities would look something like this:
// loading city data
$city = city::loadById(1); // returns a city instance
$cities = city::loadByCustomerId(1); // returns an array of city instances
// updating city data
$city->name = "Chicago"; // was "chicago"
city::update($city); // saves the change we made to $city
The static methods are not the best way to implement this, but it gets you pointed in the right direction. A repository pattern would be better, but that's beyond the scope of this one answer. I find that often I don't see the merit in a more involved solution like the repository pattern until I run into problems with the simpler solutions.
What you are doing looks greate. What you can add is an intermediate layer which maps your business object to your database(object relation mapping). There are a lot of object relational mapping api out there. Check this wikipedia list for ones you can use for PHP
I think a constructor with 28 parameters is too much, you should others classes managing some attributes having some stuff in common. You should give us what kind of others attributes you instanciated, and it could help you to find a way to make more common objects.
I think you should also create a class managing the operations and the database like a DBHandler with delete, update, and so on..
In my opinion, do modifications on tuples in your database directly after functions are called are important.
Why? Because it could avoid conflict, like the case you try to update an object which is supposed to be deleted for example, if you do modifications on your database at the end.
You might want to look at ruby on rails.
You don't necessarily have to switch over to it, but look at how they implement the MVC pattern and achieve CRUD.

PHP: Real world OOP example

I am trying to learn OOP. The so called 'real world' examples in the books I am reading aren't helping.
All the examples like Pet, Car, Human aren't helping me anymore. I need REAL LIFE examples that like registration, user profile pages, etc.
An example:
$user->userName = $_POST['userName'];//save username
$user->password = $_POST['password'];//save password
$user->saveUser();//insert in database
I've also seen:
$user->user = (array) $_POST;
where :
private $user = array();
Holds all the information in an array.
And within that same class lies
$user->getUser($uid);
// which sets the $this->user array equal to mysqli_fetch_assoc() using
//the user id.
Are there any real world examples implementing OOP in the many different php applications (registration, login, user account, etc)?
OOP is not only about how a single class looks and operates. It's also about how instances of one or more classes work together.
That's why you see so many examples based on "Cars" and "People" because they actually do a really good job of illustrating this principle.
In my opinion, the most important lessons in OOP are encapsulation and polymorphism.
Encapsulation: Coupling data and the logic which acts on that data together in a concise, logical manner
Polymorphism: The ability for one object to look-like and/or behave-like another.
A good real-world example of this would be something like a directory iterator. Where is this directory? Maybe it's a local folder, maybe it's remote like an FTP server. Who knows!
Here's a basic class tree that demonstrates encapsulation:
<?php
interface DirectoryIteratorInterface
{
/**
* #return \Traversable|array
*/
public function listDirs();
}
abstract class AbstractDirectoryIterator implements DirectoryIteratorInterface
{
protected $root;
public function __construct($root)
{
$this->root = $root;
}
}
class LocalDirectoryIterator extends AbstractDirectoryIterator
{
public function listDirs()
{
// logic to get the current directory nodes and return them
}
}
class FtpDirectoryIterator extends AbstractDirectoryIterator
{
public function listDirs()
{
// logic to get the current directory nodes and return them
}
}
Each class/object is responsible for its own method of retrieving a directory listing. The data (variables) are coupled to the logic (class functions i.e, methods) that use the data.
But the story is not over - remember how I said OOP is about how instances of classes work together, and not any single class or object?
Ok, so let's do something with this data - print it to the screen? Sure. But how? HTML? Plain-text? RSS? Let's address that.
<?php
interface DirectoryRendererInterface
{
public function render();
}
abstract class AbstractDirectoryRenderer implements DirectoryRendererInterface
{
protected $iterator;
public function __construct(DirectoryIteratorInterface $iterator)
{
$this->iterator = $iterator;
}
public function render()
{
$dirs = $this->iterator->listDirs();
foreach ($dirs as $dir) {
$this->renderDirectory($dir);
}
}
abstract protected function renderDirectory($directory);
}
class PlainTextDirectoryRenderer extends AbstractDirectoryRenderer
{
protected function renderDirectory($directory)
{
echo $directory, "\n";
}
}
class HtmlDirectoryRenderer extends AbstractDirectoryRenderer
{
protected function renderDirectory($directory)
{
echo $directory, "<br>";
}
}
Ok, now we have a couple class trees for traversing and rendering directory lists. How do we use them?
// Print a remote directory as HTML
$data = new HtmlDirectoryRenderer(
new FtpDirectoryIterator('ftp://example.com/path')
);
$data->render();
// Print a local directory a plain text
$data = new PlainTextDirectoryRenderer(
new LocalDirectoryIterator('/home/pbailey')
);
$data->render();
Now, I know what you're thinking, "But Peter, I don't need these big class trees to do this!" but if you think that then you're missing the point, much like I suspect you have been with the "Car" and "People" examples. Don't focus on the minutiae of the example - instead try to understand what's happening here.
We've created two class trees where one (*DirectoryRenderer) uses the other (*DirectoryIterator) in an expected way - this is often referred to as a contract. An instance of *DirectoryRenderer doesn't care which type of instance of *DirectoryIterator it receives, nor do instances of *DirectoryIterator care about how they're being rendered.
Why? Because we've designed them that way. They just plug into each other and work. This is OOP in action.
Purchase a book like "PHP and Mysql everyday apps for Dummies".
Its old I know [2005] but it shows concepts of User Logins, Forum, Shopping Carts, etc in both Procedural and Object Oriented with Mysqli.
It helped me learn Object Oriented PHP, I studied it a lot. Well worth the money.
OOP is much like grouping bits of your program into reuseable pieces. Its not that hard to be honest with you its just the idea of packing your functions into classes.
Real world mini example of OOP stuff below:
CLASS DATABASE
CLASS SESSIONS
CLASS WEBFORMS
CLASS EMAIL
CLASS ACCOUNTS (Example Functions below)
FUNCTION SELECTACCOUNT
FUNCTION CHECKPASSWORD
FUNCTION CHECKUSERNAME
FUNCTION CREATEACCOUNT
I hope you keep at it, PHP 6 will be re-engineered to support OOP more than ever.
Good Luck!
Whilst I know that this question has been answered already, I feel as though I can add value here.
I don't believe that you should use PHP as a programming language to learn OOP. If you wish to learn OOP for web applications, you should really be looking at C# or Java. Once you have learned OOP, then you can apply this knowledge to PHP. One example of a book I used to learn OOP was Big Java by Cay S. Horstmann
Why do I say this??? Because there are literally millions of examples on PHP of how to do stuff, however not many are examples of how to program properly. Further to this, PHP allows you to take many shortcuts, which would not be acceptable with the likes of Java. As such, if you program PHP with a Java head, then I believe that you will be a stronger programmer. OOP is not language specific, it is a programming paradigm.
If you must learn OOP using PHP, then I would recommend that you take a look at some real source code in public repositories of github. You can search them in packagist.org. If they are a decent public repository, they will contain a readme.md file which would show you how to use the composer packages. e.g https://github.com/moltin/laravel-cart is an example of a shopping cart package which you would be able to use in your application. Notice how you don't need to look at the package source code to understand what the packages do. The package has been written, and you don't care about how they work, but you use them so you only need to know how to use them. This is exactly what OOP is about.
I don't care how the shopping cart class adds an item to the cart, I just want to create a new cart and add something to it.
What you are doing however is diving into the source code as a tool to understand how OOP works.
Further to this, and probably more importantly, for web application development, I would research the MVC design pattern.
The MVC design Pattern stands for Model, View, Controller. Where in the case of a web application, The Model is responsible for modelling the database, the view is responsible for displaying content to the user. The controller is responsible for interacting with the model and handling user input.
I then think you should try to install the Laravel Framework or other "decent modern framework" on your local machine. Why do I say modern, because modern frameworks require a minumum PHP version of 5.3+ which mean that the PHP on your machine would support real OOP similar to that which you would get from the likes of Java.
There are many tutorials which will show you how to build web applications in laravel. Immediately, you will see that when you create a controller, you extend a BaseController. When you create a Model, you extend Eloquent. This means that you will already be using Polymorphism in your code. You will see that by using classes, they are being encapsulated, and you will see that each class has a specific role.
When you would like to interact with the database, you will initially create a new Model object within the controller methods. As you start to learn more, you will start learning how to inject dependencies into the controller, then learning how to dump your models and create repositories and program to interfaces instead.
A decent book on learning Laravel for beginners would be https://leanpub.com/codebright by Dale Rees. I met Dale at a Laravel meetup about 2 weeks ago.
Further to this, as you become more proficient building web applications, you will start to learn how to apply the following principles to your programming:
Single Responsibility Principle
Open Closed Principle
Liskov Substitution Principle
Interface Segragation Principle
Dependency Inversion Principle
As astropanic said, you could take a look at the source code of a good PHP framework or library. I recommend Zend Framework, it's very modular and has a great, professional design. I would say it is a very good piece of object-oriented PHP code.
Still, I think it's not that easy to learn from a huge piece of production code, since it wasn't really made to teach you anything. But if you want real-world object-oriented PHP code, the Zend Framework (or Symfony, or maybe CakePHP) is probably the way to go.
I'd advise you to stay away from any framework at this moment, if you do not know OOP, digging into zend or any other framework would be too much.
PHP OOP is quit funny... like ha ha funny, because it's supported, but PHP is not an OOP language like java or c#.
Short example just to underline my statement:
// define class
class User {
// define properties and methods
public $name = "";
}
// instantiate class
$user = new User; // or new User() or new user, it's all the same
echo $user->name;
but if you want to do OOP "on the fly" you can do the following:
$user = (object) array('name' => 'Peter');
and then
$user->name;
but you can use OOP like you would in java or c# but not to the same extend - and have in mind, popular systems like wordpress and drupal are not pure OOP! but you can do inheritance and other classing OOP stuff in PHP as well.
I haven't gone far in PHP OOP, but the more i get into it the more easier it becomes. The objects examples are just there for you to understand how OOP works. I understand and been through this before, OOP is just about properties and methods ( normal variables and functions). I programed in real OOP myself applying the examples from my tutorials and didn't necessarily have to be in real world. That is just like been spoon fed and you would never understand OOP and would be easy to forget. My advice learn to understand. If you understand, you can do anything and would realize the power of OOP. I downloaded this book and i think you should too. But that is just like someone building your apps for you...
Here a link to the book PHP and Mysql everyday Apps For Dummies
you're right 99% of the tutorials that you'll find online are too basic, and they don't make sense. My suggestion to anybody trying to learn object oriented programming is:
find some code that you've written in procedural programming and try to convert it into OOP.
Take all your variables and make them a properties of a class, find a suitable class name. Then take all your functions, if you have functions, and group them within a class. If you wrote your code without using functions, first try to convert your code into a group of functions. find suitable function names, a function should define what a piece of code does. Once you have your functions move them into a class.
I'll give you a simple example of a pagination code that I converted into a reusable pagination class. find the full tutorial on youtube: https://www.youtube.com/watch?v=X38IRlyY_ww&t=91s , link to the source code is on the description box
class Paginator{
/*the class need to know the current page to calculate the offset
the offset tell my sql how many rows to skip */
private $current_page;
//the limit is the number of results to display per page
private $limit;
/*pagination links to display below the results with next
and previous button*/
private $pagination_links;
//the last page of your pagination links
private $last_page;
.
. etc
public function __contruct($number_of_rows_found,$results_to_display_per_page){
//the paginator uses the number_of_rows_found to determine the last page
$this->last_page = $number_of_rows_found/$results_to_display_per_page;
//get the current page, set it to 1 by default
$this->current_page = isset($_GET['page']) ? ($_GET['page'] : 1;
}
public function generate_pagination_links(){
this method uses the last_page property to generate pagination links
if the last page is 3, this will give you 3 pagination links
for ($page = 1; $page <= $this->last_page; $page++) {
//use
}
}
public function get_offset_and_limit(){
//this method calculates the offset based on the current page
return "LIMIT $this->per_page OFFSET ".($this->page - 1) * $this->per_page;
}
.
.
.etc
}
}
Then to use the pagination class, you create a new instance of it, and pass the
number of results you want to display per page, and the the number of results returned
by your query as parameters. The pagination class will generate pagination links for
you and calculate the offset and limit. That's a good example of a php reusable
class, you can use it in your multiple projects without having to rewrite or change it.
$paginator = New Paginator($rows_found,8);
$pagination_links = $paginator->get_pagination_links();
$offset_and_limit = $paginator->get_offset_and_limit();
//apend the limit and offset to your sql query
$query = $query. ' '.$offset_and_limit;
$connection = getdbconnection();
$stmt = $connection->prepare($query);
$stmt->execute();
$movies = $stmt->fetchAll();
Ofcourse there're more advanced concepts into OOP that are not covered in this example, but this should give you a basic understanding of how classes and objects work
I suggest also to see my wrapper Arrayzy. It's a native PHP arrays easy manipulation library in OOP way.
So if you work with native PHP array functions - you could do the same things in OOP and Arrayzy helps you with it, for example:
// Functional programming:
$array = ['a', 'b', 'c'];
$resultArray = array_merge($array, ['c', 'd']);
and
// Object-oriented programming:
$obj = Arrayzy\MutableArray::create(['a', 'b', 'c']);
$obj->mergeWith(['c', 'd']);
$resultArray = $obj->toArray();
In both cases the result array will be:
Array(
0 => 'a'
1 => 'b'
2 => 'c'
3 => 'c'
4 => 'd'
)
Check how does this mergeWith method (or other) works under the hood.
I think this is a nice example which shows that almost everything functional code you could replace with OOP code like in this library. But with OOP you get much more and you could also check Functional programming vs OOP question to learn more details what's a cons and props of it.

Categories