Considering this simple example of classes:
// father.php
class father {
public function wallet () {}
}
// mother.php
class mother extends father { }
// daughter.php
class daughter extends mother {
public function shop {
$this->wallet();
}
}
Is there a convention/coding practice that tells you quickly that wallet() comes from class father?
This isn't a big deal but when reviewing old code (without an IDE) it's nice to know quickly where inherited methods come from.
Though seemingly trivial, one has to loop over sequence of parent's classes:
$seekMethod = 'wallet';
$stack = [];
foreach(class_parents('daughter') as $parent){
foreach((new ReflectionClass($parent))->getMethods() as $method){
if($seekMethod == $method->name){
$stack[] = "{$method->class}::{$method->name}() in {$parent}";
echo "Found ".end($stack);
}
}
}
echo "{$seekMethod} is defined in ".end($stack);
Will output something like:
Found father::wallet() in mother
Found father::wallet() in father
wallet is defined in father::wallet() in father
Or simpler, without respecting inheritance:
foreach((new ReflectionClass('daughter'))->getMethods() as $method){
if($seekMethod == $method->name){
echo "Found {$method->class}::{$method->name}";
}
}
Will output e.g.
Found father::wallet
Inheritance isn't the easiest to follow without an IDE (or a lot of documentation).
PHPDoc does have the #see tag which you could use as:
/**
* #see father::wallet() For logic pertaining to wallet retrieval
*/
public function shop {
$this->wallet();
}
Beyond that, you want to make sure your inheritance makes sense. I'm sure this was just a quick example, but I don't see any reason why a daughter would ever extend a father.
A daughter could extend a Child, and in the Child, you could have the logic pertaining to pulling the wallet from a parent (or father).
Related
Sorry for a bit misleading title but I don't quite know how to ask that better.
I have a directory with classes doing same job but with different implementation. They all look like this:
class someClass {
private static $variable=12345;
public static function someTask($keyword){
...
return array();
}
private function pf() {...}
}
The methods are taking same arguments, and returning array of the same structure.
I'd like to create one class to be able to call selected classes form that folder (and maybe each of them) combine their result, sort it by some criteria end return.
I thought of strategy pattern, but as far as I know it goes like :
$obj = new Context();
$obj->setStrategy(new ConcreteStrategy1);
$obj->getStrategy()->task(); // => „Strategy 1”
$obj->setStrategy(new ConcreteStrategy2);
$obj->getStrategy()->task(); // => „Strategy 2”
Each time I want to call another class I have to change it manually. That will leave me using foreach on some array of classes (strategies) names. Is that the right way to go? Also please help me find better title for that question because that one is misleading.
Strategy pattern it's just an algorithm that we extracted and put into some method. Then we pass the algorithm we need into context and use it there.
If you want to have one class that processes different strategies and combine their result I think Visitor pattern will be better.
I come up with a working solution
class SearchEngine {
public $instances=array();
public function __construct() {
$inputSites = $this->importClasses(); //import all classes in directory
foreach ($inputSites as $site) {
$classname = 'API\\' . $site . "Api";
$startegyInstance = new $classname();
array_push($this->instances,$startegyInstance);
}
}
public function searchByTitle($keyword) {
$results = array();
for ($i=0; $i<sizeof($this->instances); $i++){
//this searchByTitle is not recursion
$next = $this->instances[$i]->searchByTitle($keyword);
$results=array_merge($results,$next);
}
return $results;
}
private function importClasses($classesToImport){
foreach ($classesToImport as $class) {
$imp="API/".$class."Api.php";
require_once ($imp);
}
}
}
(I cut less significant details)
In classes directory I have interface and classes.
This solution works. I have not enough experience to judge it optimal or good.
I have recently started reading about dependency injection and it has made me rethink some of my designs.
The problem i have is something like this:
Let's say i have two classes: Car and Passenger;
For those two classes i have some data mappers to work with the database: CarDataMapper and PassengerDataMapper
I want to be able to do something like this in code:
$car = CarDataMapper->getCarById(23); // returns the car object
foreach($car->getPassengers() as $passenger){ // returns all passengers of that car
$passenger->doSomething();
}
Before I knew anything about DI, I would build my classes like this:
class Car {
private $_id;
private $_passengers = null;
public function getPassengers(){
if($this->_passengers === null){
$passengerDataMapper = new PassengerDataMapper;
$passengers = $passengerDataMapper->getPassengersByCarId($this->getId());
$this->setPassengers($passengers);
}
return $this->_passengers;
}
}
I would also have similar code in the Passenger->getCar() method to fetch the car the passenger is in.
I now understand that this creates dependencies (well, I understood it before too, but I wasn't aware that this is "wrong") between the Car and the Passenger objects and the data mapper objects.
While trying to think of the solution for this two options came to mind, but I don't really like any of them:
1: Doing something like this:
$car = $carDataMapper->getCarById(23);
$passengers = $passengerDataMapper->getPassengersByCarId($car->getId());
$car->setPassengers($passengers);
foreach($car->getPassengers() as $passenger){
$passenger->doSomething();
}
But what if passengers have objects that they need injected, and what if the nesting goes to ten or twenty levels... I would wind up instantiating nearly every object in the start of my application, which would in turn query the entire database during the process.
If i have to send the passenger to another object which has to do something with the objects that the passenger holds, I do not want to immediately instantiate these objects too.
2: Injecting the data mappers into the car and passenger objects and having something like this:
class Car {
private $_id;
private $_passengers = null;
private $_dataMapper = null;
public function __construct($dataMapper){
$this->setDataMapper($dataMapper);
}
public function getPassengers(){
if($this->_passengers === null && $this->_dataMapper instanceof PassengerDataMapper){
$passengers = $this->_dataMapper->getPassengersByCarId($this->getId());
$this->setPassengers($passengers);
}
return $this->_passengers;
}
}
I dont like this any better, because it's not like the Car is really unaware of the data mapper, and without the data mapper, the Car could behave unpredictably (not returning passengers, when it actually has them)
So my first question is:
Am I taking a completely wrong approach here, because, the more I look at it, the more it looks like I'm building an ORM, instead of a business layer?
The second question is:
is there a way of actually decoupling the objects and the data mappers in a way that would allow me to use the objects as described in the very first code block?
Third question:
I've seen some answers for other languages (some version of C, I think) resolving this issue with something like this described here:
What is the proper way to inject a data access dependency for lazy loading?
As I haven't had time to play with other languages, this makes no sense to me, so I'd be grateful if someone would explain the examples in the link in PHP-ish.
I have also looked at some DI frameworks, and read about DI Containers and Inversion of Control, but from what I understood they are used to define and inject dependencies for 'non dynamic' classes, where for instance, the Car would depend on the Engine, but it would not need the engine to be loaded dynamically from the db, it would simply be instantiated and injected into the Car.
Sorry for the lengthy post and thanks in advance.
Maybe off-topic, but I think that it will help you a bit:
I think that you try to achieve the perfect solution. But no matter what you come up with, in a couple of years, you will be more experienced and you'll definitely be able to improve your design.
Over the past years with my colleagues we had developed many ORMs / Business Models, but for almost every new project we were starting from scratch, since everyone was more experienced, everyone had learned from the previous mistakes and everyone had come across with new patterns and ideas. All that added an extra month or so in development, which increased the cost of the final product.
No matter how good the tools are, the key problem is that the final product must be as good as possible, at the minimum cost. The client won't care and won't pay for things that can't see or understand.
Unless, of course, you code for research or for fun.
TL;DR: Your future self will always outsmart your current self, so do not overthink about it. Just pick carefully a working solution, master it and stick with it until it won't solve your problems :D
To answer your questions:
Your code is perfectly fine, but the more you will try to make it "clever" or "abstract" or "dependency-free", the more you will lean towards an ORM.
What you want in the first code block is pretty feasible. Take a look at how the Doctrine ORM works, or this very simple ORM approach I did a few months ago for a weekend project:
https://github.com/aletzo/dweet/blob/master/app/models
I was going to say "I know this is an old question but..." then I realized you posted it 9 hours ago, which is cool, because I just came to a satisfactory 'resolution' for myself. I thought of the implementation and then I realized it is what people were calling 'dependency injection'.
Here is an example:
class Ticket {
private $__replies;
private $__replyFetcher;
private $__replyCallback;
private $__replyArgs;
public function setReplyFetcher(&$instance, $callback, array $args) {
if (!is_object($instance))
throw new Exception ('blah');
if (!is_string($callback))
throw new Exception ('blah');
if (!is_array($args) || empty($args))
throw new Exception ('blah');
$this->__replyFetcher = $instance;
$this->__replyCallback = $callback;
$this->__replyArgs = $args;
return $this;
}
public function getReplies () {
if (!is_object($this->__replyFetcher)) throw new Exception ('Fetcher not set');
return call_user_func_array(array($this->__replyFetcher,$this->__replyCallback),$this->__replyArgs);
}
}
Then, in your service layer (where you 'coordinate' actions between multiple mappers and models) you can call the 'setReplyFetcher' method on all of the ticket objects before you return them to whatever is invoking the service layer -- OR -- you could do something very similar with each mapper, by giving the mapper a private 'fetcherInstance' and 'callback' property for each mapper the object is going to need, and then set THAT up in the service layer, then the mapper will take care of preparing the objects. I am still weighing the differences between the two approaches.
Example of coordinating in the service layer:
class Some_Service_Class {
private $__mapper;
private $__otherMapper;
public function __construct() {
$this->__mapper = new Some_Mapper();
$this->__otherMapper = new Some_Other_Mapper();
}
public function getObjects() {
$objects = $this->__mapper->fetchObjects();
foreach ($objects as &$object) {
$object->setDependentObjectFetcher($this->__otherMapper,'fetchDependents',array($object->getId()));
}
return $objects;
}
}
Either way you go, the object classes are independent of mapper classes, and mapper classes are independent of each other.
EDIT: Here is an example of the other way to do it:
class Some_Service {
private $__mapper;
private $__otherMapper;
public function __construct(){
$this->__mapper = new Some_Mapper();
$this->__otherMapper = new Some_Other_Mapper();
$this->__mapper->setDependentFetcher($this->__otherMapper,'someCallback');
}
public function fetchObjects () {
return $this->__mapper->fetchObjects();
}
}
class Some_Mapper {
private $__dependentMapper;
private $__dependentCallback;
public function __construct ( $mapper, $callback ) {
if (!is_object($mapper) || !is_string($callback)) throw new Exception ('message');
$this->__dependentMapper = $mapper;
$this->__dependentCallback = $callback;
return $this;
}
public function fetchObjects() {
//Some database logic here, returns $results
$args[0] = &$this->__dependentMapper;
$args[1] = &$this->__dependentCallback;
foreach ($results as $result) {
// Do your mapping logic here, assigning values to properties of $object
$args[2] = $object->getId();
$objects[] = call_user_func_array(array($object,'setDependentFetcher'),$args)
}
}
}
As you can see, the mapper requires the other resources to be available to even be instantiated. As you can also see, with this method you are kind of limited to calling mapper functions with object ids as parameters. I'm sure with some sitting down and thinking there is an elegant solution to incorporate other parameters, say fetching 'open' tickets versus 'closed' tickets belonging to a department object.
Here is another approach I thought of. You can create a 'DAOInjection' object that acts as a container for the specific DAO, callback, and args needed to return the desired objects. The classes then only need to know about this DAOInjection class, so they are still decoupled from all of your DAOs/mappers/services/etc.
class DAOInjection {
private $_DAO;
private $_callback;
private $_args;
public function __construct($DAO, $callback, array $args){
if (!is_object($DAO)) throw new Exception;
if (!is_string($callback)) throw new Exception;
$this->_DAO = $DAO;
$this->_callback = $callback;
$this->_args = $args;
}
public function execute( $objectInstance ) {
if (!is_object($objectInstance)) throw new Exception;
$args = $this->_prepareArgs($objectInstance);
return call_user_func_array(array($this->_DAO,$this->_callback),$args);
}
private function _prepareArgs($instance) {
$args = $this->_args;
for($i=0; $i < count($args); $i++){
if ($args[$i] instanceof InjectionHelper) {
$helper = $args[$i];
$args[$i] = $helper->prepareArg($instance);
}
}
return $args;
}
}
You can also pass an 'InjectionHelper' as an argument. The InjectionHelper acts as another callback container -- this way, if you need to pass any information about the lazy-loading object to its injected DAO, you won't have to hard-code it into the object. Plus, if you need to 'pipe' methods together -- say you need to pass $this->getDepartment()->getManager()->getId() to the injected DAO for whatever reason -- you can. Simply pass it like getDepartment|getManager|getId to the InjectionHelper's constructor.
class InjectionHelper {
private $_callback;
public function __construct( $callback ) {
if (!is_string($callback)) throw new Exception;
$this->_callback = $callback;
}
public function prepareArg( $instance ) {
if (!is_object($instance)) throw new Exception;
$callback = explode("|",$this->_callback);
$firstCallback = $callback[0];
$result = $instance->$firstCallback();
array_shift($callback);
if (!empty($callback) && is_object($result)) {
for ($i=0; $i<count($callback); $i++) {
$result = $result->$callback[$i];
if (!is_object($result)) break;
}
}
return $result;
}
}
To implement this functionality in the object, you would require the injections at construction to ensure that the object has or can get all of the information it needs. Each method that uses an injection simply calls the execute() method of the respective DAOInjection.
class Some_Object {
private $_childInjection;
private $_parentInjection;
public function __construct(DAOInjection $childInj, DAOInjection $parInj) {
$this->_childInjection = $childInj;
$this->_parentInjection = $parInj;
}
public function getChildObjects() {
if ($this->_children == null)
$this->_children = $this->_childInjection->execute($this);
return $this->_children;
}
public function getParentObjects() {
if ($this->_parent == null)
$this->_parent = $this->_parentInjection->execute($this);
return $this->_parent;
}
}
I would then, in the constructor of my service class, instantiate the mappers relevant to that service using the relevant DAOInjection classes as arguments for the mappers' constructors. The mappers would then take care of making sure each object has its injections, because the mapper's job is to return complete objects and handle the saving/deleting of objects, while the service's job is to coordinate the relationships between various mappers, objects, and so on.
Ultimately you can use it to inject callbacks to services OR mappers, so say you want your 'Ticket' object to retrieve a parent user, which happens to be outside the realm of the 'Ticket Service' -- the ticket service can just inject a callback to the 'User Service', and it won't have to know a thing about how the DAL works for other objects.
Hope this helps!
So basically I'm making a leap from procedural coding to OOP.
I'm trying to implement the principles of OOP but I have a nagging feeling I'm actually just writing procedural style with Objects.
So say I have a list of pipes/chairs/printers/whatever, they are all all listed as products in my single table database. I need to build a webapp that displays the whole list and items depending on their type, emphasis is on 'correct' use of OOP and its paradigm.
Is there anything wrong about just doing it like:
CLass Show
{
public function showALL(){
$prep = "SELECT * FROM myProducts";
$q = $this->db-> prepare($prep);
$q->execute();
while ($row = $q->fetch())
{
echo "bla bla bla some arranged display".$row['something']
}
}
and then simply
$sth = new show();
$sth->showAll();
I would also implement more specific display methods like:
showSpecificProduct($id)->($id would be passed trough $_GET when user say clicks on one of the links and we would have seperate product.php file that would basically just contain
include('show.class.php');
$sth = new show();
$sth->showSpecificProduct($id);
showSpecificProduct() would be doing both select query and outputing html for display.
So to cut it short, am I going about it allright or I'm just doing procedural coding with classes and objects. Also any ideas/hints etc. on resolving it if I'm doing it wrong?
As well as the model practices described by #Phil and #Drew, I would urge you to separate your business, data and view layers.
I've included a very simple version which will need to be expanded upon in your implementation, but the idea is to keep your Db selects separate from your output and almost "joining" the two together in the controller.
class ProductController
{
public $view;
public function __construct() {
$this->view = new View;
}
public function indexAction() {
$model = new DbProductRepository;
$products = $model->fetchAll();
$this->view->products = $products;
$this->view->render('index', 'product');
}
}
class View
{
protected $_variables = array();
public function __get($name) {
return isset($this->_variables['get']) ? $this->_variables['get'] : null;
}
public function __set($name, $value) {
$this->_variables[$name] = $value;
}
public function render($action, $controller) {
require_once '/path/to/views/' . $controller . '/' . $action . '.php';
}
}
// in /path/to/views/product/index.php
foreach ($this->products as $product) {
echo "Product ID {$product['id']} - {$product['name']} - {$product['cost']}<br />\n";
}
A better fit would be to implement a repository pattern. An example interface might be
interface ProductRepository
{
public function find($id);
public function fetchAll();
}
You would then create a concrete implementation of this interface
class DbProductRepository implements ProductRepsoitory
{
private $db;
public function __construct(PDO $db)
{
$this->db = $db;
}
public function find($id)
{
// prepare execute SQL statement
// Fetch result
// return result
}
public function fetchAll()
{
// etc
}
}
It's generally a bad idea to echo directly from a method or function. Have your methods return the appropriate objects / arrays / whatever and consume those results.
The scenario you are describing above seems like a good candidate for MVC.
In your case, I would create a class strictly for accessing the data (doing selects of product categories or specific products) and then have a different file (your view) take the output and display it.
It could look something like this:
class Product_Model {
public function find($prodId) { ... }
public function fetchAll($category = '') { ... }
public function search($string) { ... }
}
Then somewhere else you can do:
$products = new Product_Model();
$list = $products->fetchAll(37); // get all from category 37
// in true MVC, you would have a view that you would assign the list to
// $view->list = $list;
foreach($ilst as $product) {
echo "Product ID {$product['id']} - {$product['name']} - {$product['cost']}<br />\n";
}
The basic principle of MVC is that you have model classes that are simply objects representing data from some data source (e.g. database). You might have a mapper that maps data from the database to and from your data objects. The controller would then fetch the data from your model classes, and send the information to the view, where the actual presentation is handled. Having view logic (html/javascript) in controllers is not desirable, and interacting directly with your data from the controller is the same.
first, you will want to look into class autoloading. This way you do not have to include each class you use, you just use it and the autoloader will find the right file to include for you.
http://php.net/manual/en/language.oop5.autoload.php
each class should have a single responsibility. you wouldn't have a single class that connects to the database, and changes some user data. instead you would have a database class that you would pass into the user class, and the user class would use the database class to access the database. each function should also have a single responsibility. you should never have an urge to put an "and" in a function name.
You wouldn't want one object to be aware of the properties of another object. this would cause making changes in one class to force you to make changes in another and it eventually gets difficult to make changes. properties should be for internal use by the object.
before you start writing a class, you should first think about how you would want to be able to use it (see test driven development). How would you want the code to look while using it?
$user = new User($db_object);
$user->load($id);
$user->setName($new_name);
$user->save();
Now that you know how you want to be able to use it, it's much easier to code it the right way.
research agile principles when you get a chance.
One rule of thumb is that class names should usually be nouns, because OOP is about having software objects that correspond to real conceptual objects. Class member functions are usually the verbs, that is, the actions you can do with an object.
In your example, show is a strange class name. A more typical way to do it would be to have a class called something like ProductViewer with a member function called show() or list(). Also, you could use subclasses as a way to get specialized capabilities such as custom views for particular product types.
Just starting out with OOP in PHP and in general. From what I have been reading so far the two seem to be synonyms. Is this the case, and if not, practically speaking when people refer to objects and classes do they generally use the terms interchangeably?
Typically one would refer to an object as an instance of a class.
So you have some class Employee.
class Employee {
var $name;
function get_name ( ) { return $this->name; }
function set_name ($new_name) { $this->name = $new_name; }
}
And you declare an instance of it like:
$assistant = new Employee();
Employee is a class. $assistant is an object, that is an instance of the Employee class.
So to answer your question - a class is not an object. You create an object when you instantiate a class.
objects and classes do they generally use the terms interchangeably?
No. As in other OOP languages, classes are like the blueprints for something, say a house. Objects are the actual house after it's built. Very different things indeed.
// blueprint
class House
{
public $color;
public function __construct($color = 'red')
{
$this->color = $color;
}
}
// make red house
$redHouse = new House();
// make blue house
$blueHouse = new House('blue');
// Now we have two different houses (objects) made from the same blueprint (class)
They're certainly not synonymous, and if you've been reading that, it's time to change the book! :-)
Classes are types, while objects are instances.
A simple example is an integer. "Integer" denotes the type, but an integer $x is an instance of that type. In PHP there isn't a strong type system, so this may not be entirely apparent, but I hope you get the idea. Similarly, array is a type, but $v = array(); creates an instance (called $v) of array type.
With classes, you cannot just say $y = MyClass(); as you do with arrays, instead, you have to use new: $y = new MyClass();.
A class is a definition of an object. An object is an instance of a class. For example:
class Parser {
public function parse() {}
}
...is a class. You might say "The Parser class can be used to parse text."
$p = new Parser;
Now, $p is an object. It is an instance of the Parser class.
This is particularly important with the static keyword. Static methods and members belong to classes, not objects.
class Parser {
public static $type;
public $text;
}
$p1 = new Parser;
$p2 = new Parser;
$p1::$type = 'php';
$p1->text = 'sometext';
$p2->text = 'someothertext';
echo $p2::$type; //echos "php"
echo $p1->text; //echos "sometext"
You can remove the in php from your question and it is still the same thing.
A class defines an Object for example
class Person {
}
is a class that defines an person object.
The distinction get more important when you start creating class methods and object methods
class Person {
function hair_color(color) {
hair_color = color;
}
}
is an object method in php you could do something like this
austin = new Person()
austin -> hair_color("brown")
now you can have something like
class Person {
total = 0;
static function total_in_class() {
total++;
}
}
now that is an class method it affects all objects of the same class
that way
austin = new Person();
austin -> total_in_class
tom = new Person();
echo tom->total
Now if my php isn't that rusty then it should echo 1. That is because all objects in the class are affected
In ruby it would look as follows
class Person
def hair_color(color)
hair_color = color;
end
def self.total_in_class()
total+=1
end
end
Similar and same concepts apply
Imagine i have 2 classes (i've simplified the logic here):
class Table {
public function addRow (Row $row){
$this->row = $row;
}
// lots of code
}
class Row {
// lots of code
}
And i want to extend the table class to do something similar so i create 2 new classes:
class SpecialTable extends Table{
public function addRow (SpecialRow $row){
parent::addRow($row);
}
// lots of code
}
class SpecialRow extends Row{
// lots of code
}
When i try to add a SpecialRow to a SpecialTable object i get a warning similar to:
PHP Strict standards: Declaration of SpecialTable::addRow() should be compatible with that of Table::addRow() in /SpecialTable.php on line XX
Can someone help me here? Is this bad practice and i should code it differently? Or is it just a warning that i should ignore?
Many thanks for any suggestions / guidance.
You should probably use a name like SpecialTable::addSpecialRow() if you're changing the argument type - otherwise SpecialTable doesn't actually extend Table, it overloads it (which isn't supported in PHP).
Based on your simplified example, it should be public function addRow(Row $row) since you just call the parent. Depending on what you're actually doing to $row in that function, you could type-hint Row and check whether it's a SpecialRow in code, or just use Row if you don't need its Specialness.
Make sure SpecialRow extends from Row:
class SpecialRow extends Row {
// lots of code
}
And that SpecialTable extends from Table:
class SpecialTable extends Table {
// lots of code
}
If Row and SpecialRow aren't directly related (where SpecialRow is a specialized Row and therefore should extend Row), you could use an interface. PHP doesn't support method overloading without some crazy ugliness, so an alternative might be something like this:
Interface:
interface IRow
{
// interface body
}
Row classes:
class Row implements IRow
{
}
class SpecialRow implements IRow
{
}
Table classes:
class Table
{
public function addRow(IRow $row)
{
$this->row = $row;
}
}
class SpecialTable
{
public function addRow(IRow $row)
{
$this->row = $row;
}
}
Implementation:
$t = new Table();
$st = new SpecialTable();
$r = new Row();
$sr = new SpecialRow();
$t->addRow($r);
$st->addRow($sr);
http://ideone.com/TsVw5
Since it doesn't follow PHP's standards I'd call it bad practice. The point is that a derivative class should always work like its ancestor. So classes expecting a Row argument can handle a SpecialRow the same way. You're extending the class, not overloading it. I'd suggest adding another method for this purpose.