Adding Functionality to Multiple Base Classes in Propel - php

I have a group of model peer classes that should all have the same functions. Rather than copying and pasting to each every time I add a new one to the group, I would rather add the functions to a class the model peer classes extend. Unfortunately, as the model peer classes extend from Base classes such as BaseModelPeer, it's not possible.
Propel 1.5 has added a basePeer attribute, which can allow you to set BaseModelPeer to extend from a given class. However, by default, a BaseModelPeer class does not extend from anything. Instead, it just makes all its calls to the BasePeer class, which has different signatures for its functions. By changing the basePeer attribute, the BaseModelPeer extends from your new class, let's call it NewBasePeer, and changes the calls to BasePeer to NewBasePeer. As the signatures differ, though, this just causes it to fall apart!
I am actually trying to follow on from Symfony's Zend Lucene tutorial, moving some of the functions which make items indexable to this NewBasePeer class. One of these functions is doDeleteAll. BaseModelPeer's signature of this function looks like this:
public static function doDeleteAll($con = null)
But inside this function it makes a call like this:
$affectedRows += BasePeer::doDeleteAll(ModelPeer::TABLE_NAME, $con, ModelPeer::DATABASE_NAME);
As BaseModelPeer doesn't extend BasePeer, it's fine. But by changing the basePeer attribute in the schema, the function call changes to:
$affectedRows += NewBasePeer::doDeleteAll(ModelPeer::TABLE_NAME, $con, ModelPeer::DATABASE_NAME);
BaseModelPeer now extends NewBasePeer, meaning for it to override the call to doDeleteAll(), they need identical signatures. Clearly the BaseModelPeer class is now contradicting itself!
Is this a bug with Propel? If not, how is one meant to use the basePeer attribute?

Rather than copying and pasting to each every time I add a new one to the group, I would rather add the functions to a class the model peer classes extend.
The correct way is to define a Propel Behavior

Related

make a static method for all classes in PHP using meta class Class?

How can I add a static method for all classes of my php using an class Class or class Object (meta class) like
class Object //meta class, all classes php henerit of it
{
static function test() { return 42; }
}
now if I make a new class like :
class User
{
}
I want to be abble to write :
User::test();
same with all classes I will write
PHP has no concept of metaclasses; the way in which classes themselves behave is essentially hard-coded into the language. (You could argue that internal classes written in C conceptually use a different metaclass than userland classes written in PHP, since they can implement a different set of hooks; but that's not a distinction that's visible in the language, and not really relevant to your example.)
It also has no universal base class; there is no "Object" or "Any" or "Mu" class which all other classes implicitly or explicitly inherit from.
More importantly, there is no way to add to an existing class; there is no way to "re-open" or "monkey-patch" a class, or add methods via "extension classes". So even if there was a default metaclass or universal base class, you wouldn't be able to change it. Any classes you wanted extra behaviour on would have to opt-in to being instances of a non-default metaclass, or inherit from a non-default base class.
It's not clear exactly what the use case is, but there are a number of things you can do:
Write your own base class which a large number of classes inherit from, to put your "universal" methods in.
Use traits which enable "horizontal code re-use", essentially by "compiler-assisted copy-and-paste".
You have to use the trait in each class where you want to "paste" its contents, but they will then be inherited from there, so you can have a handful of unrelated "base classes" all sharing a set of methods "pasted" from the same trait.
On the other hand, you might want to create a sub-class which takes an existing class and adds some methods using a trait.
More complex cases would require you to patch the source code of classes themselves. For instance, using a custom autoloader and https://github.com/nikic/php-parser to parse and manipulate class definitions before they are compiled. For instance, this just-for-fun sweary library installs as a Composer plugin and loads classes via a stream wrapper which removes restrictions such as "final".
Why not use a trait?
Unfortunately I haven't heard of anything like what you need in PHP.
<?php
trait Obj
{
static function test() { return 42; }
}
class User
{
use Obj;
}
echo User::test(); //prints 42
Hope this helps.

should my child classes inherit empty functions from parent class?

I'm trying to make a parent class and child classes, lets say the parent class is called functionality and has functions like add(), validate(), and delete(), and the child classes are driver and passenger , each of the child classes inherit the functions but needs extra parameters and different logic for each inherited function, should I define the function but leave it blank? how is this helpful apart from extendibility?, and should I define a different constructor for each child class because they have different extra variables?
class functionality
class functionality{
protected $from;
protected $to;
protected $date;
protected $name;
public function add(){
}
public function validate(){
}
public function delete(){
}
}
class driver
class driver extends functionality {
private $gasMoney
function add($from, $to, $date, $name, $gasMoney){
//some logic and adding to database
}
}
class passenger
class passenger extends functionality {
private $seatPrefrance
function add($from, $to, $date, $name, $seatPreferance){
//different logic than class driver and
}
}
is this an acceptable approach? and how would I define a constructer? should I define it in the parent class? does the child classes inherit it and can add more to it?
You shouldn't use inheritance for this, it doesn't make sense.
The main idea is that other parts of your application can receive an object, and they don't care if it's a passenger or driver, they just get some instance of functionality and call add on it.
Another reason to use inheritance if you want to take advantage of some shared behavior, so you don't have to reimplement a method.
If arguments are different based on the sub-class, there's no way anything can do something with the generic functionality class, so this is pointless.
You also can't re-use the method, because you are clearly overriding the method for each case.
Think about driver and passenger. Are there parts in your application that need to work with both? What is their actual common functionality? Anything that's not common does not go in the base class.
I know this is probably a contrived example, but it also doesn't make sense to 'add' a passenger name to an existing passenger.
If you call your class 'passenger', I would expect that to represent a single passenger, not multiple.
Learn OOP as a tool, not a religion.
If you meet an inspiring preacher, they might teach you a whole new way of thinking about the world, and suddenly you see everything in a new light. You change your diet, your daily routine, and which TV programs you watch.
If you are given a new drill as a present, you might get some scrape wood to test it out a few times, but after that you'll wait until you need to put some shelves up. You won't work out how you can pour milk through a newly drilled hole in your breakfast counter.
The example you have come up with is trying to do OOP for OOP's sake. It doesn't make any sense, because you haven't actually got a problem you're trying to solve.
In particular, don't pull out the inheritance drill until you need it. Start off by looking for ways to encapsulate state in private properties and define behaviour that is more than just accessing that state. As a silly example, $driver->canLegallyDrive() method might internally check the $insurance and $alcoholLevel properties.
Even when you find logic you want to share, composition (just storing one object in a private property of another one) is often better than inheritance. Inheritance really comes into its own when you need polymorphism - multiple objects which look the same on the outside but behave differently on the inside. And even then, learning to use interfaces rather than base classes will unlock more potential.

Design pattern to return appropriate class depending if autoloader detects file? Factory, Service Locator, etc?

We have a CMS which has standard implementations of Models, Mappers, Forms and DbTables, under the standard Admin_Model_Whatever, Admin_Model_Mapper_Whatever (Zend Framework 1 directory structure).
However, certain projects which share this CMS directory will sometimes need to add additional fields (for example, a custom "color" field for a page view). So in the original CMS directory we have Admin_Model_Page, and now I want to extend this class in the project directory with a class named Project_Model_Page (as well as new page mappers and dbtable classes).
How can I return the correct class from the shared back end implementation? That is, if Project_Class is detected and exists in that certain project's directory, return that, and if not return Admin_Class?
I'd like to avoid doing if class_exists(class) checks every time I need a different form, model, mapper, etc for every create, read, update, delete operation on every page, post, etc etc.
Is there a defined pattern to handle this? I've been looking at Factories, Service Locators, Providers and so on and so forth, but I'm not entirely certain if any of these fit this case - which is simply to have the autoloader detect if a certain class exists in one directory, and if not return a class from a default path.
The Factory-Pattern
You already were on the right track. What you might want to take a look at is the Factory-Pattern
By it's definition the Factory Pattern is a way to instantiate objects not by the classes constructor, but by another class or method.
That's how you probably want to roll. By it's simplest implementation the factory that you need to create here needs to take two arguments. The main class that you want to use and the fallback class in case the main class does not exist.
I will later show a few options how to improve the factory so that it will be able to automate things even further.
Setting up everything
For simplicitys sake I will not use an autoloader here, but using one will work just as fine.
Filesystem Structure
-Dependencies
-- DependencyRouter.php
-Fallbacks
-- FallbackRouter.php
-Interfaces
-- RouterInterface.php
-FallbackFactory.php
-index.php
The Dependencies directory contains the main classes that you want to be instantiated in the first place. The Fallbacks directory contains the corresponding fallback class in case the main class can not be instantiated.
Since both, objects of the main class and the fallback class should be able to be used the same way we will define contracts for them. We do this by creating Interfaces. That's what the last folder is for.
To not take up so much space, the gist for the actual implementations (which is not really part of the question) can be found here.
Let's now have a look on the actual Factory.
<?php
class ClassNotFoundException extends \Exception {}
class FallbackFactory {
public function createInstance( $main, $fallback, $instanceArgs = [] )
{
if( class_exists( $main) )
$reflectionClass = new \ReflectionClass( $main );
else if ( class_exists( $fallback ) )
$reflectionClass = new \ReflectionClass( $fallback );
else
throw new ClassNotFoundException('The Class ' . $main . ' does not exist and neither does the fallback class ' . $fallback);
return $reflectionClass->newInstanceArgs($instanceArgs);
}
}
There is really nothing special going on. First we look if the actual main class does exist. If it does we will store a instance of a ReflectionClass. If it does not we check if the fallback class exist. If it is the case we do the same as before. You could directly instantiate an object but let's use a ReflectionClass here to keep open some neat magic we can add later.
When neither the main class nor the exception class does exist, we should throw an Exception and pass the responsibility for handling the error to the developer.
That's really the whole magic.
index.php
<?php
require_once 'FallbackFactory.php';
require_once 'Interfaces/RouterInterface.php';
require_once 'Dependencies/DependencyRouter.php';
require_once 'Fallbacks/FallbackRouter.php';
$factory = new FallbackFactory();
$router = $factory->createInstance(
'\Dependencies\DependencyRouter',
'\Fallbacks\FallbackRouter'
);
$router->route();
That would be how to use the factory. If the main DependencyRouter could be found the output will be:
I am the main Router
If the DependencyRouter could not be found but the FallbackRouter the output will be:
I am the Fallback router
Otherwise an Exception will be thrown.
Extending the Factory
If you want to make the factory act more dynamically you could do a few things.
1. Make use of namespacing and name your classes consistent
If you want to avoid specifying a Fallback everytime you could name your main and the fallback classes the same but specify a different namespace for them. So you would need to only pass the main class. The fallback class would be determined automatically. e.g
$router = $factory->createInstance(
'\Dependencies\Router',
);
If \Dependencies\Router\ is not present, the factory would automatically look for a \Fallbacks\Router class for example.
2. Automatically resolve Dependencies
At the moment we pass in the constructor arguments as a parameter to the factory method. But by making use of Type Hinting and Reflection you could automagically resolve dependencies.
3. Specifying a Fallback-Hierarchy
Instead of passing one fallback class you could pass an array of multiple classes that all are looked up and resolved if found.

PHP workaround to extend classes of the same name?

I know extending a class with the same name is not possible, but I was curious if anyone knew of a way to load a class then rename it, so i can later extend it with the original name. Hopefully like something below:
<?php
//function to load and rename Class1 to Class2: does something like this exist?
load_and_rename_class('Class1', 'Class2');
//now i can extend the renamed class and use the original name:
class Class1 extends Class2{
}
?>
EDIT:
Well, I understand that this would be terrible practice in a basic OOP environment where there are large libraries of class files. But i'm using the CakePHP MVC framework and it would make great sense to be able to extend plugin classes in this way since the framework follows a well established naming convention (Model names, view names, controller names, url routes (http://site.com/users), etc).
As of now, to extend a CakePHP plugin (eg: Users plugin) you have to extend all the model, view, and controller classes each with different names by adding a prefix (like AppUsers) then do some more coding to rename the variable names, then you have to code the renamed url routes, etc. etc. to ultimately get back to a 'Users' name convention.
Since the MVC framework code is well organized it would easily make sense in the code if something like the above is able to be implemented.
I'm trying to work out why this would be necessary. I can only think of the following example:
In a context that you have no control over, an object is initialised:
// A class you can't change
class ImmutableClass {
private function __construct() {
$this->myObject = new AnotherImmutableClass();
}
}
$immutable = new ImmutableClass();
// And now you want to call a custom, currently non existing method on myObject
// Because for some reason you need the context that this instance provides
$immutable->myObject->yourCustomMethod();
And so now you want to add methods to AnotherImmutableClass without editing either Immutable class.
This is absolutely impossible.
All you can do from that context is to wrap that object in a decorator, or run a helper function, passing the object.
// Helper function
doSomethingToMyObject($immutable->myObject);
// Or decorator method
$myDecoratedObject = new objectDecorator($immutable->myObject);
$myDecoratedObject->doSomethingToMyObject();
Sorry if I got the wrong end of the stick.
For more information on decorators see this question:
how to implement a decorator in PHP?.
I happen to understand why you would want to do this, and have come up with a way to accomplish what the end goal is. For everyone else, this is an example of what the author may be dealing with...
Through out a CakePHP application you may have references to helper classes (as an example > $this->Form->input();)
Then at some point you may want to add something to that input() function, but still use the Form class name, because it is through out your application. At the same time though you don't want to rewrite the entire Form class, and instead just update small pieces of it. So given that requirement, the way to accomplish it is this...
You do have to copy the existing class out of the Cake core, but you do NOT make any changes to it, and then when ever you upgrade cake you simply make an exact copy to this new directory. (For example copy lib/Cake/View/Helper/FormHelper.php to app/View/Helper/CakeFormHelper.php)
You can then add a new file called app/View/Helper/FormHelper.php and have that FormHelper extend CakeFormHelper, ie.
App::uses('CakeFormHelper', 'View/Helper');
FormHelper extends CakeFormHelper {
// over write the individual pieces of the class here
}

PHP OOP - Require or Extend

I was wondering if there is any major different in the following, and whether one is more 'standard' than the other:
<?php
class Account extends Database {
public function myMethod()
{
// Do something
}
}
?>
or
<?php
require('database.class.php');
class Account {
public function myMethod()
{
// Do something
}
}
?>
Cheers :)
Edit:
This question actually relates to a tutorial series I have been following which describes the above two methods - which didn't make any clear sense.
So thank you for the constructive answers on clearing that one up!
Those are two completely separate language constructs.
Your first example deals with inheritance. Basically, you already have a class called Database, but you want to have a specialized version of that class to handle accounts. Rather than build a brand new Account class and copy/paste all the functionality you already have in your Database class, you simply tell PHP that you want to use the existing Database class as a baseline. You create any account-specific functionality in the new Account class, and anything database-related comes automatically. This is assuming, of course, that you have some way of specifying where the Database class is defined - for example, a require declaration at the top of the class, or an __autoload() or spl_autoload_register() function call defining a way to find and locate the file containing the Database class.
In your second example, your database-related code is completely separated from your Account class. They're completely distinct entities, and if you wanted to do anything database-related in your Account class, you would have to explicitly instantiate a new Database object within that class (or pass it to that class, or one of its functions, as a parameter.
Basically, extends helps define what a class is, whereas require shows where a class definition (or other code) is stored.
Both code snippets aren't even equivalent.
The first declares Account to extend Database, a is-a relation.
In the second code snippet, you are simply saying that you require 'database.class.php' ... and that neither has anything to do with OO, nor defines a is-relation from Account to Database.
Both are completely different in first one class is inherited by another class but in the second one the class is included in your script only.
Means if you extend all the public and protected methods are available in your derived class and you can create object of derived class and can use methods with derived class's object.
But in the second method the class is included in your script and require this class it's own method and work independently.
The first means you create a new class, which has all the functionality of Database class and those you implement.
The second means that you create a new class, but it doesn't have Database functionality since it's not extending it. If you need database access in your Account class, you can create an instance in constructor, or pass already created instance as constructor parameter.
It's hard to say what is more standard, since it depends on what You actually want to achieve.
To put it in most simple terms:-
require or include is structural programming.
extends is object oriented

Categories