I am currently working on a PHP project which includes extensive database usage. The basics are: I have a PDOFactory class which follows the Factory pattern and an abstract SQL class with static methods (just a container for those methods) which in turn talks to PDOFactory
As I said, the project involves extensive database usage, so the SQL class will contain numerous methods. However, they could be easily grouped, depending on what they deal with (i.e. session storage, user logging on/off, etc.). That would make the SQL class much easier to maintain and so on and forth. And here comes the big question: Can I have the source of the class contents spread across many files? There could be (at least) two possible solutions to this problem:
Multiple inheritance, i.e. having classes SQLSession, SQLUser, SQLblahblah and making the SQL class inherit all of them.
C++-like pre-processor* directives, i.e. #include SQLSession.php; or something like that.
I know there is no multiple inheritance in PHP, so that rules out option No. 1. Is option No. 2 even possible? Or does anybody know of better solutions to this problem?
*Or actually pre-pre-processor directives, since PHP is a pre-processor. :)
EDIT:
Here's an attempt to answer this question, based on Kalium's suggestion. It's a mess to read, but it works. However, I'm gonna stick with Bill's method as it's way cleaner.
class SQL {
private static $oInstance = false;
public static function getInstance()
{
if( self::$oInstance == false )
{
self::$oInstance = new self();
}
return self::$oInstance;
}
public $SESSION;
private function __construct()
{
$this->SESSION = new SESSION;
}
}
// this would be in another file
class SESSION {
public function printOne()
{
echo "One";
}
}
SQL::getInstance()->SESSION->printOne(); // outputs "One"
?>
I think you may be approaching this wrong. That's certainly not the best way to go about it. Try breaking the many functions into smaller utility classes and then using those to composite a larger class.
Don't use static methods, as it makes it hard to use something else than the SQL class
Use small classes, which have a single responsibility.
I think you should use the Builder pattern for your SQL instead of a motley container of static methods.
No, there is no multiple inheritance in PHP. Use delegation instead.
No, you can't include files to define methods of a class. You can only include files in contexts where code is executing, not in the middle of a class definition:
<?php
include("define-functions.php"); // OK
class Foo
{
include("define-methods.php"); // ERROR
function foo()
{
include("method-body.php"); // OK
}
}
PHP Parse error: syntax error, unexpected T_INCLUDE, expecting T_FUNCTION
in foo.php on line 7
Re your comment:
Since you're committed to using only static methods, why bother with a class at all? Just define functions in the global scope. Then you can include() as many as you want:
<?php
include("SQLSession.php");
include("SQLUser.php");
include("SQLblahblah.php");
SQLSession.php:
<?php
function SQLSessionStart()
{
...
}
function SQLSessionEnd()
{
...
}
You don't have access to static class member data with this solution, but you can just use global variables.
to me, it sounds like you're trying to create a monolithic chunk of code, which is the exact opposite of class based OO code - I'd recommend following the DAO blueprint of the Java core patterns, and implementing it in PHP for what you want to do :) that should cover all you're questions
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'm wanting to gauge people's opinions on the use of static classes instead of namespaces. I come from a C++ background and am quite fond of its syntax and how it lets you structure code. I recently decided I needed to group my code into logical units instead of just files. For instance I prefer calls like User::login to user_login. So, I did a bit of googling and was relieved to find that PHP has namespaces. My relief didn't last long though, I really don't like the syntax; it adds more mess to my function calls. So, at the moment I'm using static classes to simulate namespaces. Are there any downsides to this?
I found a similar question at PHP Namespaces vs Classes with static functions but there wasn't a whole lot of discussion.
Also, is there a way to avoid the following situation:
class Test {
public static void myFunc() {
Test::myOtherFunc();
}
public static void myOtherFunc() {
}
}
I assumed it would be ok to call functions in the same class without specifying the name, but apparently not. Are there any workarounds for that (for instance in C++ there the using keyword).
Coincidentally I've actually been moving into the exact opposite direction:
Use namespaces to organize domain classes (or functions)
Use dependency injection where I would have otherwise used static classes
The thing with static classes to simulate namespaces is that you can't organize them across multiple files, everything has to be defined inside one file; this may well be up to personal taste.
The other thing about static classes is that you start without any state and slowly some state management creeps in and you end up with some weird lock-in dependency. State should be reserved for instances. Currently my only notable static class is the site-wide configuration.
Lastly, self referencing in static classes is explicit, whereas in namespaces it works exactly like C++ would: you specify the function name and it gets looked up within the namespace first.
If you look from the standpoint of code structure, there is no difference between static class method and namespaced function. They both end up in global scope. Only difference is, that, with static class method, you are trying to fake OOP.
Therefor it is better to use namespaced functions, if what you really need are standalone/utility functions. Namespaces are for grouping thing (both function and classes).
As for you User::login() example, it would be a bad practices. Instead you should have a real object, which is able to capable of containing state.
$mapper = new UserMapper;
$user = new User;
$user->setNickname( $name );
$mapper->fetch( $user );
if ( $user->hasPassword( $password ) )
{
$user->setLastLogin( time() );
}
else
{
// log the access attempt
// set error state
}
$mapper->save( $user );
The bottom line is this: if you are using static structures ( functions or methods ), it is not OOP. You are just faking it. Instead you should use real OOP, with dependency injection.
If your code uses static methods and variables all over the place, it causes tight coupling between classes, add global state and makes harder to maintain and test your codebase. And this is not PHP specific.
While creating classes, I followed OO conventions and declared all class variables before using them:
class myClass {
private $property1, $property2, ...;
public __constructor() {
$this->property1 = $this->property2 = NULL;
}
}
But I realized that PHP is scripting language and not following OO concepts strictly, so we can 'generate' class property dynamically:
class myClass {
public __constructor() {
$this->fields = $this->db->getFields(TABLE_NAME);
foreach($this->fields as $fld) {
$this->{$fld} = NULL;
}
}
}
Is this a good approach ?
I think dynamically generated properties would have public access by default, so that could be one disadvantage and such automation could be one advantage.
Is there any difference in terms of performance ?
You're not encouraged to do so, but in some cases you just need to (like in ORM, which you seem to be writing). Classes should have clean interfaces (programmer needs to know what can he do with your class).
But there's a better way of handling these cases (at least, it seems better for me). Prepare an associative array of data in your class and use __get method. It can be even better for an ORM (you may implement lazy loading, etc.).
If you're writing code (library) that many users should use, it would be better to be strict in the definition of your API. so that there would be less mess when implementing it. but if you're using it for a single case it wouldn't be so bad, in fact it could provide much flexibility.
This depends on your situation. This is a common practice when you have have data containers that are mapped directly to tables (or some other structure). Most commonly used in ORMs because the columns are determined at run time and you don't need to define a container class for each of your tables.
It all depends on how you want to make use of those publicly available variables. For example in frameworks like Symfony make very good use of them. all dynamic class variable are can be made available outside the class in templates and such.
So it can be a good practice if you are creative with them
I just want to tell you that I am newbie to OOP and it is quite hard to me, but here is my code:
class functions
{
function safe_query($string)
{
$string = mysql_escape_string(htmlspecialchars($string));
return $string;
}
}
class info
{
public $text;
function infos($value)
{
echo functions::safe_query($value);
}
}
Is there any way to make this sentence : echo functions::safe_query($value); prettier? I can use extends, than I could write echo $this->safe_query($value);, but is it a best way? Thank you.
edit: and maybe I even can to not use class functions and just make separate file of functions and include that?
Yes, just define your function outside of a class definition.
function safe_query($string){
return mysql_escape_string(htmlspecialchars($string));
}
Then call it like this
safe_query($string);
Using a functional class is perfectly fine, but it may not the best way to design your application.
For instance, you might have a generic 'string' or 'data' class with static methods like this (implementation missing, obviously):
class strfunc{
public static function truncate($string, $chars);
public static function find_prefix($array);
public static function strip_prefix($string);
public static function to_slug($string); #strtolower + preg_replace
etc.
}
The point of a class like this is to provide you with a collection of generic, algorithmic solutions that you will reuse in different parts of your application. Declaring methods like these as static obviates their functional nature, and means they aren't attached to any particular set of data.
On the other hand, some behaviors, like escaping data for a query, are more specific to a particular set of data. It would probably be more appropriate to write something like this, in that case:
class db_wrapper{
public function __construct($params); #connect to db
public function escape($string);
public function query($sql);
public function get_results();
}
In this case, you can see that all of the methods are related to a database object. You might later use this object as part of another object that needs to access the database.
The essence of OOP is to keep both the data and its relevant behavior (methods) in one place, called an object. Having behavior and data in the same place makes it easier to control data by making sure that the behavior attached to the data is the only behavior allowed to change it (this is called encapsulation).
Further, having the data and behavior in one place means that you can easily pass that object (data and behavior) around to different parts of your application, increasing code reuse. This takes the form of composition and inheritance.
If you're interested in a book, The Object-Oriented Thought Process makes for a decent read. Or you can check out the free Building Skills in Object-Oriented Design from SO's S.Lott. (Tip: PHP syntax is more similar to Java than Python.)
Functions outside a class litter the global namespace, and it's an open invitation to slide back to procedural programming. Since you're moving to the OOP mindset, functions::safe_query($value); is definitely prettier (and cleaner) than a function declared outside a class. refrain from using define() too. but having a functions class that's a mix of unrelated methods isn't the best approach either.
Is there any way to make this sentence
: echo functions::safe_query($value);
prettier?
Not really. IMO having a functions class serves no purpose, simply make it a global function (if it's not part of a more logical class, such as Database) so you can do safe_query($value); instead.
and maybe I even can to not use class
functions and just make separate file
of functions and include that?
Create files for logical blocks of code, not for what type of code it is. Don't create a file for "functions", create a file for "database related code".
Starting with OOP can be a real challenge. One of the things I did was looking at how things were done in the Zend Framework. Not only read the manual (http://www.framework.zend.com/manual/en/zend.filter.input.html, but also look at the source code. It will take some effort but it pays of.
Looking at the context of your question and the code example you posted, I would advice you to look at some basic patterns, including a simple form of MVC, and the principles they are based upon.
I need some advise on my PHP code organisation.
I need classes where I can store different functions, and I need access to those classes in different parts of my project. Making an object of this classes each time is too sadly, so I've found a two ways have to solve it.
First is to use static methods, like
class car {
public static $wheels_count = 4;
public static function change_wheels_count($new_count) {
car::$wheels_count = $new_count;
} }
Second is to use singleton pattern:
class Example {
// Hold an instance of the class
private static $instance;
// The singleton method
public static function singleton()
{
if (!isset(self::$instance)) {
$c = __CLASS__;
self::$instance = new $c;
}
return self::$instance;
} }
But author of the article about singletons said, that if I have too much singletons in my code I should reconstruct it. But I need a lot of such classes.
Can anybody explain pros and cons of each way? Which is mostly used? Are there more beautiful ways?
See this excellent post:
Singleton Pattern vs Static Classes
More Resources:
How Bad Are Singletons?
Static DB class vs DB singleton object
When you say that you need to use a class of some sort to store functions, I am presuming that you'd normally be fine using plain functions but you do not want to pollute the global scope. This problem you will run into all the time in PHP.
If you are lucky to be working with PHP 5.3 you can use namespaces to pull the functions out of the global scope. Effectively, namespaces serve as a convenient way to auto-complete the prefixes you would normally have on functions to try and ensure their uniqueness. Because of this primitive implementation, there is no access control available for namespaces. If you wish to design an interface, you are out of luck, as all functions are globally accessible.
In this case, use a static class. No, it is certainly not the most beautiful solution but it is literally the best PHP can offer. With a static class you can effectively both prefix your functions for uniqueness and use access control.
Singletons are an object-oriented concept that solve a different problem. If your original design involves no objects, don't introduce them now.
That said, you have a function called change_wheels_count(). This function has a notion of state, and whenever you need state you need an object. I do not know if your code was just a quick example or your actual situation. If it was your actual situation, I would say you need neither a static class or a singleton.