I am wondering if such this subclassing structure is possible in PHP. If this is a duplicate I apologize as I couldn't figure out what this process would be called and the only I could find was a closed question with no answer.
I am working with multiple classes. For example we will say Main and User.
The Main class will hold all of the initiation code. So
class Main{
//Setters for core variables and data needed to make calls
...
protected function fetchInfo(){
//Do Stuff to return info from other source(Curl calls in my case)
}
}
and User
class User extends Main{
public function getName(){
$data = $this->fetchInfo();
return $data['name'];
}
}
But instead of having it where I would. Do $exampe1 = new Main(...); to set varaibles, and $example2 = new User(); to call the subclass to do $example2->getName(); is there a way to do something like $example = new Main(); whcih could then call the subclasses when needed like $example->User->getName();?
I know there are a lot of different ways this could be handled, but I want the classes separate for organization and I plan on having a lot of subclasses that need to pull info from that main class and would like to know if there is a way they can be linked in that fashion.
EDIT: The reason I dont want to just call User calls to get the function is I'll end up having 15+ classes that handle the returned data differently and making wonder if there was a better way than making a new Object for each one if I want to use it.
A "Main" is not a "User" so I would say this type of subclassing is a poor choice.
I might instead look at injection.
class MainDataHandler {
//...
}
class User {
private $main;
public function __construct(MainDataHandler $main) {
$this->main = $main;
}
public function getName() {
return $this->main->getData('name');
}
}
The benefits of injection is that your classes can work and be tested independently without dependencies on another class to do the work. Also if "Main" ever changes you your User class isn't dependent on how the new Main works.
Related
This is a very basic architectural question and it is thus very hypothetical.
Imagine this simple setup:
I have a class representing a web object, with only one method that renders the object. However, this class extends a parent class which requires certain conditions to be met, so that the method is actually executed (so that the object is being rendered).
Example
class webObject__adminBase {
protected function shouldRender(){
return access::isAdmin();
}
}
class webObject__adminPanel extends webObject__adminBase {
public function invoke(){
if(!parent::shouldRender())
return;
// if still here, render the object
}
}
$panel = new webObject__adminPanel();
$panel->invoke();
The code above serves both: an example plus a practical explanatory approach to the problem.
The issue is: i would like to get around this problem without actually having to call a method in my parent class in the child's rendering method.
I would like to achieve a class design that assures that all i need to do is to extend the parent class webObject__adminBase. Any calls to any methods in my child class should be checked against certain conditions (as in this example systemAccess::isAdmin()) and only render if these conditions are met.
I hope my description is clear.
Since someone actually requested to close this question as "too broad", i decided to rephrase my actual question with a more direct reference to the question title:
Is there a way to intercept the progression (or even execution) of a child's method based on a condition checked for by its parent class (without calling a method on that parent class) ?
Here is one method of doing it, albeit quite simple. I'm sure there are better methods but this one tries to keep to your original methodology.
https://ideone.com/D5hA3H
Render Class
abstract class Render
{
abstract public function main();
public function __construct()
{
}
final public function render()
{
if (!$this->canRender()) return '';
return $this->main();
}
final public function canRender()
{
// Logic here
return true;
}
}
Admin Panel Class
class AdminPanel extends Render
{
public function main()
{
return "Admin Panel";
}
}
Execution
$panel = new AdminPanel();
echo $panel->render();
PeeHaa is right about the naming conventions, it is in the best interest to try and follow a popular coding style which allows you yourself to read code easier and vice versa. You might want to take a look at the PHP-FIG PSR one and two standards which helps in creating consistent code.
PHP The Right Way is also a great website that will help you out the most, it provides information about dependency injection and coding practices amongst other things.
Through my multiple studies I have come across the factory method of setting session and database objects which I have been using while in development. What I am wondering is, putting aside personal preference (although I will soak in any opinions anyone has), does this general method work, and is it efficient (meaning, am I using it correctly)? If it is not, do you have suggestions for how to improve it?
Background
I created the code this way so as to pass a database and session object to the class upon calling the class. I wanted to be able to pass along the relevant objects/references so that they could be used.
The Call Class
This class is meant to call static functions, like so:
class CALL {
public static $_db, $_session;
public status function class1() {
$function = new class1();
$function->set_session(self::$_session);
$function->set_database(self::$_db);
return $function;
}
public status function class2() {
...
}
...
}
The _set class
class _set {
public $_db, $_session;
public function __construct() { ... }
public function set_database($_db) {
$this->_db = $_db;
}
public function set_session($_session) {
$this->_session = $_session;
}
}
Now the classes referenced.
class class1 extends _set {
function __construct() { ... }
function function1() { return "foo"; }
...
}
So, moving forward, the classes would be called using CALL::class1 or CALL::class2. After that, they can be accessed as per usual, aka:
CALL::$_db = $database->_dbObject;
CALL::$_session = $_SESSION;
$class1 = CALL::class1;
echo $class1->function1(); //prints "foo".
Read about Dependency Injection . Small suggestion from my point of view, you should never create objects like $db or $session inside other objects. You should rather inject them through constructor or setter method. It will make your code less dependant on a specific classes and it will be easier to replace all dependencies almost without refactoring (actually without one if you know hot to use interfaces).
If anyone stumbles on this, I will share with you what my solution was.
Although this exercise helped me to learn a lot, and I am sure I could take the time to create a VERY highly functional factory/Container, because this is not integral to my program and not even unique, I finally bowed to the age old wisdom of not repeating something that has already been done.
I utilized Pimple, a lightweight library that uses PHP closures to create function calls. Now, I can haave the flexibility of determining which dependency injections I want, but I also only need to inject them once. Future calls, even when they create new instances, will replicate them. While I think that, in theory, my project was workable as it was, it did indeed have the unfortunate issue of requiring you to go into the container to make changes. With Pimple I do not need to do that. So I've tossed by Container class and picked up a lightweight program from the maker of Symfony. While this may not be the best answer for everyone, it was for me. Cheers!
I am trying to develop an object oriented PHP application in which whole php application will be extending from MyApplicationBase base class. But the problems is I want to create only single instance of MyApplicationBase. Below is the code which explains what I mean
class MyApplicationBase{
static $called=0;
public var $db;
function __construct()
{
self::$called++;
echo "<pre>MyApplicationBase Created ".self::$called." times</pre>";
$this->db=new DatabaseWrapper();
}
}
class ApplicationSecurity extends MyApplicationBase{
function is_logged_in()
{
$res=$this->db->query("user check db query goes here");
return ($res)?true:false;
}
//..... other methods related to ApplicationSecurity class
}
class ApplicationBusinessLogic extends MyApplicationBase{
// business logic methods here which may use base class vars like $db
// this may also use instance of ApplicationSecurity class
}
class ApplicationTemplating extends MyApplicationBase{
protected function outputHeader()
{
require_once('path/to/themes/header.php');
}
protected function outputSidebar()
{
require_once('path/to/themes/siderbar.php');
}
protected function outputMainbody()
{
require_once('path/to/themes/mainbody.php');
$app=new ApplicationBusinessLogic();
$app->initiate();
}
protected function outputFooter()
{
require_once('path/to/themes/footer.php');
}
public function outputTemplate()
{
$this->outputHeader();
$this->outputSidebar();
$this->outputMainbody();
$this->outputFooter();
}
}
//index.php file code starts here--------
$myPhpApplication = new ApplicationTemplating();
$myPhpApplication->outputTemplate();
My goal is when I create instance of my application then It only call the single instance of "MyApplicationBase" class instead of calling it multiple times. Please do tell me how can I achieve this. I am google for 5 hours but unable to find any solution yet.
I am trying to develop an object oriented PHP application in which whole php application will be extending from MyApplicationBase base class.
As PHP has single inheritance, this is by far the most worst idea to do object oriented PHP programming.
But the problems is I want to create only single instance of MyApplicationBase.
As every class is a MyApplicationBase you actually don't want that because it would mean you could instantiate exactly one class in your whole application.
What you're probably looking for is some kind of ApplicationClass which you pass along and of which just a single instance exists.
This would at least allow you in the future to throw such a "block in road" away more easily then if you would have got extended from there.
In any case you should program against an ApplicationInterface instead of an ApplicationClass to make this throwing away - as it will be necessary - easier.
The best thing for sure would be to not do anything in that direction and only write code you need in the first place.
To only write code you need, you need to develop test-driven. Why not start with that if you want to do object oriented programming?
Well I suppose that you want to avoid multiple connections to the database in this case. Solution is simple with Dependency injection, just initialize your database connection outside of MyApplicationBase class and then pass it as a constructor parameter (beware of constuctor hell though). Like this:
class MyApplicationBase{
static $called=0;
public $db;
function __construct($db)
{
self::$called++;
echo "<pre>MyApplicationBase Created ".self::$called." times</pre>";
$this->db= $d;
}
}
$db = new DatabaseWrapper();
$templating = new ApplicationTemplating($db);
$security = new ApplicationSecurity($db);
You could also take a look at some framework, they usually come with some dependency injection capabilities.
I'm pretty new to the MVC concept itself but I'm slowly starting to grasp it, and what it is that makes it so useful.
I have in my app different tabs which are levels in a hierarchy (I call them entities), each represented by two classes - a Binding class with all the methods to communicate with the database and a helper class which is just a skeleton of the Entity, both in same file. I wonder if this is the right way to approach the design pattern? I haven't built a Model or a Controller yet because I'm not sure where they'll come in at the moment. Also I'm not interested to use ORM right now.
class CompanyBinding extends EntityBinding {
function __construct() {
parent::__construct();
}
public function get($criteria = array()) {
// method to retrieve an array of DB rows, each represented by the helper class
[...]
return $sth->fetchAll(PDO::FETCH_CLASS, 'Company');
}
public function get_by_id($id) {
// method to retrieve an one single object of the helper class
$sth->setFetchMode(PDO::FETCH_CLASS, 'Company');
return $sth->fetch();
}
}
class Company extends Entity {
public $id;
public $name;
public $email;
public $phone;
// just properties. some classes have a __construct() function to manipulate some fields after retrieval
[...]
}
Do I need a model class now? I was considering the Controller could perform the ->get function and load appropriate class, because the name of the entity is passed from the front-end with AJAX.
By the way I also am really confused. Should the controller absorb all AJAX requests or should I make a file called ajax.php that handles that, and put the Controller class above public_html so users can't access the class file?
Separate the classes into their own files. PHP does a decent job at caching file locations once it opens them, so you don't have to worry about IO. And generally speaking, it is bad practice to put multiple classes in one file. It won't break your application, but it may cause more seasoned developers to break-down into tears. :)
Apart from that, you are fine.
If I have two classes that each extend a common parent, is it possible to convert between them?
class Foo
{
public $bar;
}
class FooDatabase extends Foo
{
public function load() {}
public function save() {}
}
class FooFlatfile extends Foo
{
public function load() {}
public function save() {}
}
$foo = new FooDatabase;
$foo->bar = 'elf';
Using this code as an example, I want to convert $foo from an instance of FooDatabase to FooFlatfile, while retaining the value of the property bar.
Edit: I do realise that actually doing this isn't such a great idea in practice. Rather, I came across a situation in which this was a potential fix, and became curious about how it might be achieved.
This is possible although not advised. Take a look at A dark corner of PHP: class casting. Basically:
Serialize the class;
Change the class name in the serialized form; then
Deserialize it.
Yes, it's a hack.
The bigger question: is why do you want to do this? If you have the need to change class it's a very strong indicator that your object model is bad. It reminds me of the old examples of introductory OO they used to give:
Person class;
Salesman extends Person;
Manager extends Person.
which is a horrible example for the same reason: what if someone changes from a Salesman to a Manager? Compare that to the composition-based approach where Person has-a Job (where Manager and Salesman are instances or subclasses of Job). Much more sound approach.
Lastly, I'll add that if some code you can't change is forcing you to do this, you'd be best off using some sort of adapter or facade:
class A { ... }
class B {
public function asA() {
$ret = new A;
// configure;
return $ret;
}
...
}
Again this is much more sound than any sort of automatic property copying class changing process.
Can you accomplish what you need by creating a new one and copying the values over?
$foo2 = new FooFlatFile;
$foo2 = foo->bar;
If doesn't get done what you need, please give us more details.
Response to comment:
If you are planning on doing that often, it would be easy to create a member function to return all members in some sort of array or struct. However, at that point, you really need to ask yourself "why am I doing this?" The other responder is spot on in saying that if you are regularly wanting to do this, you have designed your classes very badly.
If you've got two classes you are wanting to switch between, remove what is separating them, and make one class. Either they are fundamentally the same, in which case you could get away with switching between them, but you would be far better served by making just one class.
Or they are fundamentally different from each other, in which case you still need two classes. If you have a database, and you're trying to turn it into a flat file, you need to have an export function translate the database into flat data. Dynamically changing classes would be like using Notepad to open up an Oracle file: it would not yield the data in a meaningful, usable manner. To go between them, you write 'export' and 'import' functions that use the same data structure as each other. You create a new one, export from the old, import into the new, and delete the old.
I'm frankly not sure what else to say, because I can't imagine a scenario where it would make sense to do this. If you could give more details about the background of what you're trying to solve, I could offer better advice.
You can do something like this, has some limitations (limits on types of constructors and can't copy private vars) but it can be made to work.
class Foo {
public $bar;
protected function convertTo($classname) {
$rc_other_class = new ReflectionClass($classname);
if ($rc_other_class->isSubclassOf(get_class())) {
// there's a limitation here in that the constructor can't take params
$other_class = new $classname();
$rc_this_class = new ReflectionClass(get_class());
$properties = $rc_this_class->getProperties();
foreach ($properties as $property) {
if (!$property->isStatic() &&
$property->getDeclaringClass()->getName() == get_class()) {
$property = $property->getName();
if (property_exists($this, $property)) {
// this will throw if you try to copy a private var, add a filter to
// getProperties to prevent this but you probably want the error
$other_class->$property = $this->$property;
}
}
}
} else {
return false;
}
}
}