Say I have the following, is this valid code? -
<?php
include_once('HelloWorld.class.php'); // contains class 'HelloWorld'
class user
{
function hello() {
$HelloWorld = new HelloWorld; //Loads HelloWorld class into variable
$HelloWorld->hello(); // calls hello function
}
}
$go = new user; // loads user class into variable
$go->hello(); // calls user 'hello' function, which in turns utilizes 'HelloWorld' class
?>
Essentially, the "user" class utilizes another class.
What I am trying to achieve -
I want to make the "user" class accessible and editable by someone (perhaps via a gui). They can edit the "user" class any way they see fit. However, I don't want them to be able to view the source of "HelloWorld.class.php". Is this possible?
Would they simply be able to retrieve the contents by? -
$lines = file("*path*\HelloWorld.class.php");
Yeah but you could also write your engine separately and nest it, then make your public classes extend the engine. No need for all this classes instantiating other classes to avoid whatever it is you're avoiding.
I agree with the others in redundancy and the fact that you're letting anyone modify any class on your site. Unless you're Johnny McSuper-Coder then you won't want to deal with the security provisions you'll need to write into your user based update script to prevent them from just wrecking everything in any way they can.
I bet some decent planning would reveal any number of better options for your end goal. Not quite sure about how the SO community will feel if you generically post a question about how to go about doing whatever it is you're up to here though.
Related
I'd like to apologise for the ambiguous title, it's the best one I could think of to define my problem.
I've got a single class in PHP that I want to be invoked from other scripts and I have a few libraries that I want to be able to call functions from, but I want to be able to call those functions from the other libraries via the single class I already have.
class Core
{
// code
}
I want to essentially do the following, Function->Core->Library Function.
The reasoning behind this is that I don't want to have a bunch of classes that get included when the file is run, causing the user to have to remember a bunch of different class names.
This is what I would essentially hope to achieve (but i'm pretty sure this is incorrect syntax)
$Core->Data->Get();
tadaam. That calls for Dependency Injection ;)
class Core
{
public $lib1;
public $lib2;
public function __construct(){
$this->lib1 = new Lib1Class();
$this->lib2 = new Lib2Class();
}
}
I wrote a wordpress plugin that works fine. However, it just works but there is no OOP here because at that time it was necessary to build something asap. I read some literature and found that php do not support multiple inheritance due to diamond problem.
Current scenario:
Flickr
--pic importer
----1. sql.php
----2. javascript.php
----3. call to show database contents
--photoset importer
----1. sql.php
----2. javascript.php
----3. call to show database contents
Here, I have created 2 class: picImporter and photosetImporter. Both classes share common contents from (1. sql.php and 2. javascript.php) but point-3 (implementation of showing database content is differnt for them).
So, my idea is: I should create another class Global and photosetImporter, picImporter class should extend this class. In the Global class there should be an abstract class that child class must define. So the design becomes:
Class Global{
//$sql comes sql.php,
//$javacript comes javascript.php,
abstract protected function showDatabaseContents();
}
Class picImporter extends Global{
protected function showDatabaseContents() {
//implementation using **$sql** from base
}
}
Class photosetImporter extends Global{
protected function showDatabaseContents() {
//implementation using **$javascript** from base
}
}
Before I proceed, I just want to know if I am on right track or not and further instruction if possible.
Thanks,
-S.
There's no particular "right" way to do what you're looking for (though there are wrong ways). Hard to know what method I would use without understanding what your javascript class does.
Typically, I create a single global DB abstraction class (what I assume your sql class is) and just access it from the global scope wherever I need it. Global scope isn't evil, especially for things like database access which aren't inherent to whatever other classes you're creating but are needed pretty much everywhere. The same may be true for your javascript class.
That said, if you need this sort of abstraction to maintain a consistent design in your application, then I see no problem with what you're doing here, this seems like a logical approach.
If you're looking for what might be a best practice, run a search for "PHP design patterns", but in general my approach with PHP is to keep it simple and accessible. That may mean using a design pattern, or it may mean a more basic approach, depending.
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
}
I read this post after doing a search for related posts.
I have a slightly different, but related problem.
Is there a way WITHOUT EVAL() (because this is a bad idea - open for abuse if someone allows a user to supply the value that is used in eval, etc) such that you can define the structure of the class, for example:
if(!class_exists($className) && dao::tableExists($className)) {
class $className extends daoObject {
public function __construct($uid) {
parent::__construct($uid);
}
}
dao::generateClass($className);
}
The reason for this is because when new core tables are added to a framework, they could be used with a generic data access object for accessing the corresponding fields (getters/setters via __call in the parent, add/insert and update/delete) without writing a class for each, without requiring the coder to write a class and then having to inspect it or writing custom code generators for the various types of tables. the daoObject does that all for me.
The intention is to use this kind of method to define a class if it doesn't exist, then write the class definition to a file.
If the corresponding table name doesn't exist, it will fail. If the class exists (e.g. the next time it is run) then it won't define it. If it doesn't exist but is a tablename, you could create it, use it and save it the first time you call it, which would occur when new tables are inserted and a script is run to insert data. The authors will define only the table fields and sample data via csv. This script will generate classes and import the data in one hit. I COULD write the definition to a file, then include it, which seems like it could work, but I want to do that AFTER I've modified the properties of the object so I don't have to write to files twice to make it work.
This is simplified, but is it possible?
I don't think it's possible; as you said, the best option is probably to write the class to a file, then autoload that/those classes.
You can't use a variable for a class name (unless as you say, with eval()).
So if you really need to create DAO objects at runtime for tables for which no class is defined, perhaps you should make a DAO class for "other table" and pass the name of the table in the constructor.
class OtherTable extends daoObject {
public function __construct($uid, $tableName) {
$this->table = $tableName;
parent::__construct($uid);
}
}
$FootballTable = new OtherTable($uid, 'football');
trigger_error("You need a new table class!", E_USER_WARNING);
If your logs show that you have any of these user-warnings, you should use that as a reminder to go create a proper class for the new table(s).
Re your comment:
Generating code for a new class at runtime, even as a fallback condition, is not a good habit. The risk is that some untrusted content sneaks into your class definition (such as user input, but it can be something else). Then you have a Code Injection security problem.
Either you need a generic any-table DAO class like I showed, or else the best solution is that you create new DAO classes during development, at the time you create new tables in your database. Why is that not your solution?
I have a class called "Layout" for the layout of the page, another class called "User" for the user.
Every page I create, I instantiate a new Layout.
When a user logs in, there is a new User instantiated.
How do I get an instance of the layout class to know about the instantiated user? I could also save the entire instance of the User in a session variable. I assume that's a bad idea though. What are the best practices for this?
class User
{
var $userid;
var $email;
var $username;
function User($user)
{
$this->userid = $this->getUid($user);
$this->email = $this->getEmail($user);
$this->username = $user;
}
function getUid($u)
{
...
}
function getEmail($u)
{
...
}
}
class Layout
{
var $var1;
var $var2;
var $var3;
function Layout()
{
//defaults...
}
function function1()
{
echo "something";
}
function function2()
{
echo "some other stuff";
}
function function3()
{
echo "something else";
}
}
so in index.php, for example, i would do the following:
include "user.php"
include "layout.php"
$homelayout = new Layout();
$homelayout->function1();
$homelayout->function2();
$homelayout->function3();
now let's say that in login.php someone logged in:
include "layout.php"
include "user.php"
if(userAuthSuccess)
{
$currentUser = new User($_POST['username']);
}
what is the best way to gain access to $currentUser and it's member variables such as $currentUser->email, etc. from all php files from here on out, as long as the user hasn't logged out?
I think the best remedy to the solution stated above is going for a concept called Dependency Injection, whereby you write an extra class, that will inject the dependency (An Object in this case) to the requesting class. Most of the modern developers will adhere to using this technique of injecting dependencies into their applications as this will enable:
Loosely coupled programs - As the dependency is injected by a third class, there is no need to hard code the dependency in the logic of the program.
Maintainable code - This is that feature of the OOP paradigm that allures the most. This is especially true when referring to large scale programs.
Memory Management - As a developer, you are free to manage the memory to your specification requirements.
Since there will be only one User for every request and thus for every run of your program, this would be a case to make "User" a Singleton class as described here:
http://php.net/manual/en/language.oop5.patterns.php
That would provide the one way for other classes to refer to the current user without the chance of accessing the wrong instance since there is only one.
DISCLAIMER:
Yes, I know that Singeltons are often used at the wrong places for the wrong purpose and some people tend to blame this problem on the pattern instead of the people who misused it for some smelly code.
This however is a perfectly good use case for the Singelton pattern.
"Globalizing" something by putting it in a session variable or cookie for the sole purpose of globalizing it is a very bad habit to get into, and it leads to tightly coupled libraries that rely on an arbitrary variable being set outside the class. Session variables in general are good to stay away from for other reasons, too.
The best way to get a variable into any class is to pass it as an argument. Do you have a method in your Layout class that renders (outputs) it? You may want to add a $data argument to that method that takes an associative array of data usable in the layout.
I'd personally use a registry class (Singleton) and register the user there for the Layout to access. That way, you only need to pass an instance of the registry to the Layout.
The User class is not integral to the Layout's construction - since it should only be concerned with the Layout, so I wouldn't pass that in the constructor.
Another method would be to use a Controller to orchestrate these interactions between Views and Models. Whenever a new Controller is created, buffer it's output. Then, at render time, unbuffer the contents and assign them to properties (or a property array) of the view, which can then render them. You probably don't need an actual Model class to be passed to the View/Layout - just it's output.
Use a registry pattern. No need to make it a singleton, everyone is throwing that word around.
include "layout.php"
include "user.php"
if(userAuthSuccess)
{
$data['currentUser'] = new User($_POST['username']);
}
$data['nav'] = new nav('home');
$homelayout = new Layout( $data );
Now $homelayout can access $data (which contains all the variables you put into it) via the data array.