Having the option of customized classes but a unified class name - php

Suppose you are building a web application that is going to be a packaged product one day, one that users will want to be able to extend and customize.
It comes with a core library consisting of PHP files containing classes:
/library/
/library/frontend.class.php
/library/filesystem.class.php
/library/backend.class.php
Now, suppose you want to keep a clean core that users can't patch. Still, you want the user to be able to customize every nut and bolt if need be.
My current idea is to create an autoloading mechanism that, when a class is instantiated, first loads the core include:
/library/frontend.class.php
then, it switches to the user directory and looks whether there is an include of the same name:
/user/library/frontend.class.php
if one exists, it includes that as well.
Obviously, the user include must contain a class definition that extends the definition in the core include.
Now my question is, how would I instantiate such a class? After all, I can always be sure there is a definition of:
class frontend_core
but I can not be sure there is a
class frontend_user extends frontend_core
However, I would like to be able to rely on, and instantiate, one class name, regardless of whether there was a custom extension to the class or not.
Is there a clever way, idea, or pattern how to achieve this?
Of course, I could write a simple factory helper function that looks for the user class first and then for the core class and returns an initialized object, but I would really like to keep this as clean and simple as possible, because as I said, it is going to be a packaged product.
I am looking for a smart trick or pattern that uses as little code, and introduces as little new functionality, as possible.

Why don't you follow the approach as used by Propel? You generate your base classes and already provide an empty User class (extending the base class) where your users can put their overrides/specific implementation details, and in your code you always refer to the User classes. So basically you just use the inverse of the logic you described.
If the explanation above isn't clear, check out http://propel.phpdb.org/trac/wiki/Users/Documentation/1.4/QuickStart#a6.UsingtheGeneratedSQLandOMFiles and generate code for a small database. The base classes are in the om folder, the (by default empty) user classes are in the root folder.

I would implement hooks in the core, so users dont have to hack the core, but are still able to extend the core using hooks

I'd go with using the constructor of the core class to determine the user class to load, and then implement a factory method in the core class to generate instances of the user class. By making the constructor of the user class protected, and having the user class extend the core class you can be sure that code elsewhere cannot instantiate the user class.
C.

I think it's more complicated with a single filename when you want to use inheritance as well. Basically class user_frontend extends core_frontend has to know where to find both classes. Both must be included.
If you just want to do new Frontend you could use PHP5.3's class_alias to point Frontend to the main class to use. Below 5.3. you could use a ServiceFinder, that knows how to map Service Names to Classes and then get the Frontend with $service->get('frontend') or use a Dependency Injection framework.
Edit I removed the Loader code given before, because it was suffering from exactly this problem.

You could have a loader class that will decide which class to instance:
Loader::instance()->load('Frontend')

Related

Is there an app_fixture.php or behavior for CakePHP?

I want to add a function that will be used by several fixtures in my app, and it would be nice to be able to put it somewhere reflecting that it's an extension to CakeTestFixture. In a Model, I could do this by writing a Behavior or adding it to app_model.php. Is there a way to do this for fixtures?
I can always just add it to my static Utility class, but it would be nice to be able to structure it better.
Write an AppTestFixture which extends CakeTestFixture and include it in there. Obviously each fixture then has to extend your new class instead of Cake's one.

CModel subclass in yii

I am a 4 days old yii fan and I like it so much.
I have a special database table that can't be used by CActiveRecord directly. My solution is to subclass CModel to have my own logic for listing, creating, saving and deleting records. My new CModel subclass cant not instantiated; it seems that CModel requires more methods to be defined to allow creating an instance from it.
My question is: Is this the right approach to go or there are better ways? If yes, what are the missing methods to define to make my new class complete; not abstract
Thanks
I usually create my own classes to handle the so called 'logic' of the webapp that I'm building.
I place it in another folder (usually the logics folder) and auto import the directory from the config. The logic classes doesn't subclass from any Model
public class ProfitLogic { ... }
where inside the class(es) I implement functions that instantiates and use any ActiveRecord(s) that I need.
The reasoning for this is that when prototyping I often refine my database design, and I need to regenerate the ActiveRecords again :p
Your approach is fine generally speaking, and would be fine even if you were not "forced" to adopt it. I use a CActiveRecord subclass as the base for my models to provide additional custom functionality.
As for your other question, you only need to implement attributeNames() to be able to instantiate objects of your class.
However, why do you not subclass CActiveRecord directly instead of CModel? You can still override any and all methods you choose to. Is your database so dramatically different from the usual schemas that you won't be able to reuse any of the logic?
I'm fairly new to Yii as well, but have found that extending CForm, as in the default ContactForm model can be useful.
Not the best for having lots of heavy business logic, but it touches on your point of breaking out of the typical workflow.

Confused About Objects and Classes in CodeIgniter?

I’m fairly new to CodeIgniter and have a question. I’m a bit confused about Classes, Libraries and Objects.
Does CodeIgniter replace the normal PHP way of usings objects i.e. $var = new car(); with libraries i.e. $this->load->library('some_library'); $this->some_library->some_function(); ?
If both are valid, is there a difference? If so, what are the differences and when do I use one over the other? Which is more common/proper?
I am asking because I created a class, but I'm not certain what is the correct manner in which to instantiate it.
Thanks in advance
I am not familiar with CodeIgnitier. But familiar with other PHP frameworks. Most of frameworks use this way for performance improvements, registering things, executing certain events, and making things simpler for developer...
For example if you want to create class "car" with is somewhere in library directory you would have to include the file first before you can create object of that class (miltiple lines of code, more room for error). The framework will create the class and includes related files in 1 line of code (easier and safer).
Framework way also works as a factory. Instead of recreating an object, it will create object only once and every time you call the method again it will return the reference to existing object.
More things are happening behind the scenes when you use framework. Things are getting registered, etc...
CI doesn't replace class behavior per se, it simply adds functionality that allows access to custom libraries/models/views as singleton objects via the core object for simplicity.
Nothing is stopping you from creating (as I have in one of my projects) additional files with classes for non-singleton entities and require them in a model for further use. On hindsight, I should probably have used helpers for this.
What the loader ($this->load) class does, among other things, is it creates a single object of the specified class (model, library or view - not helpers though, see below) and attaches it as a property of the core class that is normally accessible via $this.
Helpers are a bit different. They are not attached, but instead simply 'read' into the global namespace from the point where they are loaded.
To answer your question, it would be more proper to use the loader class in instances where you don't need more than one instance of a class created. If you need 'entity' classes, your best CI-compliant bet would be to create them as helpers.
Given only this context, this looks like Inversion of Control (maybe I'm wrong, I haven't looked too closely at CodeIgniter).
You don't want to rely on the type car as in new car(). What if later you want to make $var a racecar? $var can still do the same things, but it is forced to be a car because you constructed it directly. Or what if you are testing this class, but car is some complex object which calls some external service. You want to test your logic, but don't care if the car service isn't working. So you should be able to change $var to actually load a mockcar. You can't do that if you do $var = new car().
What is Inversion of Control?

In an MVC Context, Where Do I Put A Class?

straight to the point :
I am using Kohana, and I am looking at another script written in plain PHP. In the script, I have a class ShoppingCart. If I am to convert the script to Kohana, where am I to put the class, its methods and its properties?
Is it in my existing default controller? Or should I put it in a separate controller? Or as noobie as it may sound, will I put it in the model?
That depends on the specifics of the class I suppose. To be honest I don't know anything about Kohana, but there's probably a place for "vendor files" somewhere. Maybe it's best to place it there and write wrapper functions for it in your controller. If the class already integrates well with Kohana you may instead choose to use it as a controller or model directly. Or you might want to take the time to rewrite it to make it work as a controller...
Only you can evaluate the best place for it, there's no hard and fast rule here.
Kohana has a folder for 3rd party libraries. The main one is under system/vendor, you can put it in you application/ as well.
Many PHP class loaders require details like your filename should be the same as the class name (at least that's what I read in the Kohana documentation) if you want the classes to be automatically loaded.
If you need to use 3rd party code in your app it's recommended that you create a folder in your app / module folder called 'vendor' and place all of that code there.
You can then include the files by calling:
include kohana::find_file('vendor', 'filename');
If needs be you can also create a wrapper for the external library, a good example of this is the email helper which uses the 3rd party Swift email library.
If you're porting your own class to kohana then you need to work out what the class will be doing and categorise it accordingly.
If the class will be fetching items from some kind of database then you should make it a model. Libraries are usually sets of code that you want reuse across controllers / models, such as authentication, calendar generation etc. Controllers are used for passing data from models to your views / libraries.
See the docs for more info
As per kohana convention, you should place custom classes in application/libraries folder. However for this, you need to know how to get the class to work after putting it there. If you can't figure that out, you can do anything like putting it in your controller or making another controller of it, etc.

PHP classes: Need help to inherit two classes

I need help in designing my PHP classes where I need to extend from multiple classes.
I have a general class, Pagination.php that does all sort of pagination and sorting. All other classes will use this for pagination.
To make my life easier, I made a class generator that generates a class from MySQL table. All the properties, getters, setters and common methods are created automatically, which really saves time and money.
As an example, class Staff_Base in Staff_Base.php is generated automatically from SQL table t_staff.
Since class Staff_Base is automatically generated from SQL table, any 'custom' methods / properties are located in another class that extends Staff_Base.php. (So that whenever a new field is added, I can simply regenerate Staff_Base class and overwrite in Staff_Base.php).
So I have class Staff.php that extends Staff_Base.php.
The problem is, Staff.php also needs to extend another class, Pagination.php.
(The current workaround is to put methods in Pagination.php into every class. This is really troublesome whenever I make changes to the pagination/sorting methods.)
How do I do this?
What is the best design pattern to achieve this?
I know common suggestions to restructure my classes, but I really think hard of other workaround/solution. Also, I may also need to extend other classes than Pagination.php.
Thanks!
Can you have your generated Staff_Base class inherit from Pagination? Or does Staff_Base already inherit from another base class (that you do not have control over)...
Sounds like either Doctrine or Propel, I do not recall which uses the *_Base class system.
My suggestion would be to rewrite pagination to be able to be used by your entity classes instead of requiring your entity classes to extend it.
So if I am reading what you wrote correctly, since you can't inherit from 2 classes you are duplicating paginate into every class you have.
Class stacking is a solution. One of the first things I googled.
I would recommend changing your Staff_Base.php generator to make that class extend Pagination by default. That way Staff extends Staff_Base, and Staff_Base extends Pagination. I think that's probably the cleanest (and most object-oriented) way of getting the results you want.
you cant, multiple inheritance is not supported in php, but if you do a google search on this topic you can find some workarounds...
It sounds like you're mixing things up here. A class (such as a Staff class) is used to represent a single entity. Eg:
$john = new Staff('John');
How exactly does the paging fit into this? Being page-able (paginatable?) sounds like a property of whatever it is that allows access to these Staff entities, not of the entity itself. That way, the way is clear for each type of Staff class you create to inherit from the base class.
So, what I believe would be the solution you need:
A Staff class (Staff_Base, and its graph of children)
A Staff Data Access Object (DAO\Staff would be a nice name, if you're using namespaces)
An Interface, to signal to the world that a DAO can be paged
Import to note is that there is no direct inheritance between the DAO class and the Staff class. You can still generate the Staff_Base class based on its properties in the database, and extend from there... as long as you don't include the actual data access in that class.
The code using this would then look something like this:
<?php
$staffDao = new DAO\Staff;
$staffMembers = $staffDao->getPagedResult($start, $amount);
?>
Edited to emphasize that the inheritance structure should be separate from the actual retrieval
Well, you might already know that PHP doesn't support multiple inheritance. One way around might be using Interfaces instead of superclasses, although, if the logic is identical for each implementing of the interface, this might become tedious. How about writing a code generator, that simply injects the methods to each class? You seem to already do that on the "common methods".
Oh, and using getters and setters (as they are used in e.g. Java) in PHP is considered not a good idea. Objects are slow as they are, so using public fields is considered the norm.
Edit: Then there's the __call()-hack, which could recognize the methods that actually reside in your other classes, and call them manually.

Categories