Okay, I am wanting to expand my armoury within PHP, so I've been researching OO PHP. With my researched knowledge I went on to create a quick script that reads a CSV file and outputs the results.
CSV Class:
class CSV {
private $file;
public function __construct($filename, $mode) {
$this->file = fopen($filename, $mode);
}
public function endFile() {
return feof($this->file);
}
public function getCSV($mode) {
return fgetcsv($this->file, $mode);
}
public function close() {
fclose($this->file);
}
}
The test file:
require('class.csv.php');
$csv = new CSV('postcodes.csv', 'r');
while(!$csv->endFile()) {
$postcode = $csv->getCSV(1024);
echo $postcode[0] . "<br />";
}
$csv->close();
I am just wondering if there are... or what are the improvements I could make in regards to the OO approach. This is purely a script for me to put the knowledge i've learnt together. I'm not another 'following the crowd person' who creates every script in an OO approach because they 'can'.
I understand it is a short script but I am wanting to make sure I have the correct approach before moving forward.
The only possibly thing I can think of that would improve the code is to have less in your main test file. A general idea of using object-oriented code is that you can do a lot with the class itself and less in the main file.
So for example, say you needed to do exactly what you're doing in the test file again later on in the code. You would need to complete duplicate the while loop again. Instead, maybe write a method that handles the algorithm your while loop is doing and call that instead. Then later on, you could just call that method again and it's that simple!
The best part is, you can use the methods from your class inside other methods in the class. Like the endFile() method could be called from another method by saying $this->endFile() the same way that you are calling $file by saying $this->file
Otherwise, I'd say you're looking good!
Related
I am trying to write class code that can dynamically load external function code
to use as methods of the class. I understand that I could use extends and create
child objects, but it seems there would be a simpler way of going about this.
The point is to limit to bare essentials the amount of code that has to be
used to perform a particular function. And keep all the function code in separate files
that can be required.
class _DEMO
{
public $_addOn = '';
public function __construct()
{
require_once('DEMOAdd.php');
$this->addOn = addOn;
}
}
In DEMOAdd.php:
function addOn($_input)
{
return 'getting '.$_input;
}
How would I load this into the _DEMO class? The above produces fatal error.
print $_test->addOn('something');
In JavaScript it is possible to assign a function to a variable. I realize this
is not JavaScript, but I suspect there is analogous functionality in PHP.
I am also aware of variable variables in PHP but I am having trouble wrapping my brain around that concept.
In response to this advice
When another developer looks at your code it is just not clear what the particular role of this class is. Instead he has to inspect many files and external functions referenced in the class. It just would be better if he could take a look at the class and see "oh, that class does this and that". That's even a central aspect of object oriented programming.
I agree with you on this. I am working on a project that I am the only developer of everything, html, javascript, css,
and php. I have been using class definitions lately, but have written lots of procedural code in the past. The current
project has code that is sectioned off into several class def files so code can be reused in different contexts. My
consideration is if a query from a web page only needs 500 lines of code, why load 1500 lines of code to service the
request. Additionally, this is a cms system with a very limited amount of users (only me at present), so the volume
of traffic is not an issue. But if there was a larger user load, for each user extra code is required, thus the amount
of server memory require increased significantly. The cms web interface is to manage content that direct revision of code
would be very difficult. Yes, I am reinventing the wheel. So has Firestone, General, Nokian, etc etc etc.
Thank you all for the answers
I think I have the answer in anonymous functions that can be assigned to variables, re the php manual
$_var = function($_input)
{
return "getting ".$_input;
}
print $_var('something'); // I have to look back at the manual to varify this line's syntax... yep it looks good.
By using inheritance. You can extend the _DEMO class like this:
class _DEMO_ADD extends _DEMO {
...
function addOn(....) {
...
}
See docs on extends.
Designing the application properly
First of all. What you're trying to do violates fundamental aspects of clean object oriented design. Why even use a class when it's only purpose is to call an external function? If you want to proceed with it stick to functional programming.
The point is to limit to bare essentials the amount of code that has to be used to perform a particular function. And keep all the function code in separate files that can be required.
The attempt of good design is not (only) the amount of code you write, but rather how a certain task is achieved. If a class is suitable for solving your problem then use a class.
When another developer looks at your code it is just not clear what the particular role of this class is. Instead he has to inspect many files and external functions referenced in the class. It just would be better if he could take a look at the class and see "oh, that class does this and that". That's even a central aspect of object oriented programming.
Okay. Enough for off-topic. Since you ask especially for that certain problem I'll give you a few advices on that altough I don't recommend it and would advise to rethink your design.
Dynamic method calls
To call a function that has been defined somewhere else we will make use of the magic method __call($methodname, $args). This method will be called whenever you try to access classes method that does not exists.
Within this __call() method we will check if a function with the name of the method exists, we were trying to call. If not we can throw an Exception, otherwise we're going to execute the function using call_user_func_array().
functions.php
<?php
function addOn($input){
echo "This function is procedural and takes the param: " . $input;
}
MyClass.php
<?php
class MyClass{
// This will get called whenever a method on this class
// is called that does not exist
public function __call($name, $args)
{
// Let's check if a function called like the method we wanted
// to call exists somewhere
if(!function_exists($name))
{
// No? So let's raise an Exception
throw new Exception("The function you called " . $name . " does not exist");
}
// Such a function seems to exist so call it and pass
// the arguments
call_user_func_array($name, $args);
}
public function __construct()
{
// Call undefined method
$this->addOn('My Input');
}
}
index.php
<?php
include 'functions.php';
include 'MyClass.php';
$cls = new MyClass();
Here it is, but with some limitations though...
<?php
class SomeClass
{
private $_funcs = array();
public function setFunc($name,$func)
{
$this->_funcs[$name] = $func;
}
public function __call($name, $param)
{
if(!function_exists($name))
{
if(isset($this->_funcs[$name]))
$this->_funcs[$name]();
else echo "NO $name <br />";
}
}
public function dummy()
{
echo 'DUMMY<br />';
}
}
Then let's test this:
$sc = new SomeClass();
$sc->haha();
$sc->dummy();
$sc->setFunc('foo',function(){echo 'Hello New World!';});
// blah blah blah...
// blah blah blah...
// blah blah blah...
// blah blah blah...
// blah blah blah...
$sc->foo();
One of the limitation that I thought of is how to determine if you want to return a result from $sc level or not.
The result should be, based from the code above:
NO haha
DUMMY
Hello New World!
NOTE: I know this is not the best practice, OP, you should know it too. I just answered OP's question.
EDIT: To be able to determine if the function should return something, try taking advantage of the function name like r_sum with a prefix of r_ to determine that it needs to return something.
Example:
public function __call($name, $param)
{
if(!function_exists($name))
{
if(isset($this->_funcs[$name]))
{
if(strpos($name, 'r_')===0)
return $this->_funcs[$name](); // execute and return
else
$this->_funcs[$name](); // just execute
}
else echo "NO $name <br />";
}
}
But now, the other issue of this that I almost forgot, you cannot access the class properties via, new funcs.
SUGGESTION
Group your similar or related functions together into one static class so you can reuse your codes anytime anywhere.
//APP contains functions designed closely to work with your CMS
// example
APP::abort();
// HTML contains functions like getting page title, external reso, etc
// example
echo HTML::getTitle();
// ROUTE contains many routing reqs that you may need
// example
ROUTE::to('heaven');
// many more...
There is like a million Template Engine for PHP (Blade, Twig, Smarty, Mustache, ...), and i just hate the idea of creating a new syntax and compiler to write PHP inside HTML! I think it's just not smart (but this isn't what i am here to discuss :) ), what is wrong with writing PHP+HTML the usual way - not for logic - you know, all the variables and loops and defines you wanna use without this {{% %}} or that {:: ::} ! At least for performance sake!
Now, i am using Laravel these days , and it's awesome; it offers (besides Blade and any other 3rd party engine) a plain PHP templates system that uses ob_start/include/ob_get_clean and eval. I was very happy to know that i can avoid learning a new syntax to write PHP inside HTML.
Here is what i am suggesting; what about instead of using ob_* functions with include, we use Closures ? Here is a simple class i put together just to make a point:
class Templates{
static public $templates = array();
static public function create($name, $code){
self::$templates[$name] = $code;
}
static public function run($name, $data){
if(!isset(self::$templates[$name]) || !is_callable(self::$templates[$name])) return false;
return call_user_func(self::$templates[$name], $data);
}
}
And here is how to use it:
Templates::create('test', function($data){
return 'Hi '.$data['name'].' ! ';
});
for($i =0; $i < 10; $i++){
print Templates::run('test', array('name' => 'Jhon'));
}
I think this way is much better, since i wont need to do any output buffering or use eval. And to "separate concerns" here, we can put the Templates::create code in a separate file to keep things clean, in fact this way things can become more simple and elegant; we can make another method to load the template file:
static public function load($name){
self::create($name, include($name.'.php'));
}
And the content of the template file will be as simple as this:
return function($data){
return 'Hi '.$data['name'].' ! ';
};
What do you think of this ? Is there any problems with the approach or the performance of such use of Closures ?
I do not think there are any problems besides that if you put all closure functions into array, that would possibly mean that functions are kinda doing basically the same stuff.
What I mean by this:
In your example you have your functions accepting only 1 parameter. So, not to create a mess all functions you create would accept the same set of parameters and return the same type of data.
However when declared apart, functions may be supposed to do something different and unique.
Why such a solution is suitable: when using some engines, there may be a lot of different functions declared already. To resolve the conflict, they can be "hidden" inside arrays.
Also, some people even say that anonymous functions can be generally better in case of performance. But we have to test that first: to call a function you:
Call a static function run
Check a function for existence
Check a function for callability
And then use call_user_func which returns the return of your function. So, 3x return.
Update
My recomendations for you code:
Make all possible checks only when creating a function. That will greatly buff performance.
static public function create($name, $code){
if (!isset(self::$templates[$name])){
if (is_callable($code)){
self::$templates[$name] = $code ;
} else {
//func is not callable, Throw an exception.
}
} else {
//function already exists. Throw an exception.
}
}
That way you just can have 2x increase in performance:
static public function run($name, $data){
if (isset(self::$templates[$name])){
self::$templates[$name]($data); //Just make a straight call
} else {
//throw new Exception(0, "The func is not defined") ;
}
}
I need some advice on how I can proceed with this issue.
Using PHP
An example would be:
class BuilderClass {
function getClass($id, $some, $vars){
$dbResult = new db_Class::getDbRows($id, $some, $vars);
foreach(...)
// Build something from the database values
return self;
}
}
So what I want to do is to create a test case where I somehow mock the db results.
I have not found any great way to do this, please point me in the right direction or similar to get this working for me.
I could change something within the builder itself for example call a class that runs the function: FunctionRunner::runStaticFunction("db_Class", "getDbRows", $args, $something_else); But at the moment I don't know if that is possible neither. Any research articles that cover this or any sites that explain this. I'd appriciate anything at the moment.
Thanks
/Marcus
Split the operations of retrieving data from database, and building the data.
class BuilderClass {
function getClass($id, $some, $vars){
$dbResult = new db_Class::getDbRows($id, $some, $vars);
return doGetClass($dbResult);
}
function doGetClass($dbResult) {
foreach(...)
// Build something from the database values
return self;
}
}
That way, you can test doGetClass in isolation from calling the database .
As often the case, inability to easily write tests for your functions is caused by a flaw in your application design. In this case the db_Class is tightly coupled to your BuilderClass.
A proper solution would be to have a Database object in your BuilderClass using dependency injection, and mocking that injection to return a static result.
class BuilderClass
{
protected $oDatabase;
public function __construct(db_Class $oDatabase) {
$this->oDatabase = $oDataabse;
}
public function getClass($someVars) {
$this->oDatabase->getDbRows($someVars);
}
}
This way, the Database object is easily replaced with a stub.
There are many ways to do this, but since we are talking PHP, you could leverage the magic class loader function.
Simply put, if you want to mock the data access layer, you just create an object with the actual name of the data class, and the autoloader is never called.
Want to actually access the database? don't define the class and the autoloader will be called when something tries to access the database, which should then know what to do to load the class.
Mostly my autoloaders, when I use them, tend to look something like this;
function __autoload($className)
{
if(file_exists('../includes/'.$className.'.php'))
require_once('../includes/'.$className.'.php');
}
Please give me some real life examples when you had to use __destruct in your classes.
Ok, since my last answer apparently didn't hit the mark, let me try this again. There are plenty of resources and examples on the internet for this topic. Doing a bit of searching and browsing other framework's code and you'll see some pretty good examples...
Don't forget that just because PHP will close resources on termination for you doesn't mean that it's bad to explictly close them when you no longer need them (or good to not close them)... It depends on the use case (is it being used right up to the end, or is there one call early on and then not needed again for the rest of execution)...
Now, we know that __destruct is called when the object is destroyed. Logically, what happens if the object is destroyed? Well, it means it's no longer available. So if it has resources open, doesn't it make sense to close those resources as it's being destroyed? Sure, in the average web page, the page is going to terminate shortly after, so letting PHP close them usually isn't terrible. However, what happens if for some reason the script is long-running? Then you have a resource leak. So why not just close everything when you no longer need it (or considering the scope of the destructor, when it's no longer available)?
Here's some examples in real world frameworks:
Lithium's lithium\net\Socket class
Kohana's Memcached Driver
Joomla's FTP Implementation
Zend Frameworks's SMTP Mail Transport Class
CodeIgniter's TTemplate Class
A Tidy Filter Helper for Cake
A Google-Groups Thread about using Destructors For the Symfony Session Class
The interesting thing is that Kohana keeps track of the tags, so that it can delete by "namespace" later (instead of just clearing the cache). So it uses the destructor to flush those changes to the hard storage.
The CodeIgniter class also does something interesting in that it adds debugging output to the output stream in the destructor. I'm not saying this is good, but it's an example of yet another use...
I personally use destructors whenever I have long running processes on my master controller. In the constructor, I check for a pid file. If that file exists (And its process is still running), I throw an exception. If not, I create a file with the current processes id. Then, in the destructor I remove that file. So it's more about cleaning up after itself than just freeing resources...
There is another handy use to generate HTML page
class HTMLgenerator {
function __construct() {
echo "<html><body>";
}
function __destruct() {
echo "</body></html>";
}
}
With this class, you can write
$html = new HTMLgenerator();
echo "Hello, world!";
And the result is
<html><body>Hello, world!</body></html>
For example:
<?php
class Session
{
protected $data = array();
public function __construct()
{
// load session data from database or file
}
// get and set functions
public function __destruct()
{
// store session data in database or file
}
};
This is a good why to use destruct. You prevents reading and writing to a session source all the time and do this only at the start and at the end.
I create a php page what will generate a movie information jpg file. This page will have to gather a few information and run inkscape to convert template (an svg file) to a png before converting to jpg. The svg contain relative links to other image which must be a file. So my page download necessary files into a temporary folder, convert the svg file. At the end, the temporary folder must be deleted.
I put the temporary folder deletion into the destructor. Before there can be many reason the page ends unexpected and the only think I can be sure is that destructor will be call when page exit.
Hope this helps.
A destructor is extremely useful if you use a custom database connector/wrapper.
In the constructor, you can pass the connection information. Because you can use a destructor (rather than a finalizer, etc.,) you can rely on that to close the connection for you. It's more of a convenience, but it certainly is useful.
For example, when PHP decides to explicitly "free" the object (i.e., it is no longer used,) it will call the destructor at that time. This is more useful in the scenario I describe as you're not waiting for the garbage collector to run and call the finalizer.
$0.02
Ian
<?php
class Database
{
private $connection;
private $cache = array();
function __construct([$params])
{
//Connection here
}
//Query
public function query(Query $Query)
{
if($this->is_cached($Query->checksum))
{
return $this->get_cache($Query->checksum);
}
//...
}
public function __destruct()
{
unset($this->connection);
$this->WriteCache();
unset($this->cache);
shutdown_log($this,'Destruction Completed');
}
}
?>
theres an example that should make you understand.
If you use handles returned by fopen() for say, logging, you can use __destruct() to make sure fclose() is called on our resources when your class is destroyed.
You are right, __destruct is mostly unnecessary for the short running php scripts. Database connections, file handles and so on close on script exit or sometimes even earlier if variables run out of scope.
One example i can think of is writing logs to the database. Since we didn't want to fire one query per log entry that gets created somewhere in the script we wrote the "write to db" part in the __destruct of the logging class so when the script ends everything gets inserted into the database at one.
Another example: If you allow a user to upload files the destructor is sometimes a nice places to delete the temp file (in case something goes wrong in the script it at least get cleaned up)
But even for filehandles it can be useful. I've worked on a application that did use the old fopen etc. calls wrapped in objects and when using those on large filetrees php would run out of filehandles sooner or later, so cleaning up while the script was running was not only nice but necessary.
I use APC caching for large numbers of "low level" objects, that otherwise would use excessive memory; and I have a cacheCollection object that handles the reading and writing of those "low level" objects to and from APC during execution of the script. When the script terminates, the objects must be cleared down from APC, so I use the cacheCollection __destruct method to perform that function.
I have used __destruct() in a logging class that wrapped a database connection:
<?php
class anyWrap
{
private $obj,$calls,$log,$hooks;
function anyWrap($obj, $logfile = NULL)
{
if(is_null($logfile))
{
$this->log = dirname(__FILE__) . "/../logs/wrapLog.txt";
}
$this->hooks = array();
$this->dbCalls = 0;
$this->obj = $obj;
}
public function __set($attri, $val) {
$this->obj->$attri = $val;
}
public function __get($attri) {
return $this->obj->$attri;
}
public function __hook($method)
{
$this->hooks[] = $method;
}
public function __call($name,$args)
{
$this->calls++;
if(in_array($name,$this->hooks))
{
file_put_contents($this->log,var_export($args,TRUE)."\r\n",FILE_APPEND);
}
return call_user_func_array(array($this->obj,$name),$args);
}
//On destruction log diagnostics
public function __destruct()
{
unset($this->dbReal);
file_put_contents($this->log,$this->calls."\r\n",FILE_APPEND);
}
}
The script hooks into the database calls and logs the prepare statements, then when the script has run to an end (I don't always know when) it will finally log the number of calls to the database to the file. This way I can see how many times certain functions has been called on the database and plan my optimization accordingly.
If you are creating a view using a PHP script in a MySQL database, you must drop that view at the end of the script. Because if not, the next time that script is executed view will not be created, as there is already a view of similar name in the database. For this purpose you can use destructor.
Here's a rather unusual use case for destructors that I think libraries such as pest are using to combine method chaining with functions or in other words, to achieve fluent interface for functions, Which goes like this:
<?php
class TestCase {
private $message;
private $closure;
private $endingMessage;
public function __construct($message, $closure) {
$this->message = $message;
$this->closure = $closure;
}
public function addEndingMessage($message) {
$this->endingMessage = $message;
return $this;
}
private function getClosure() {
return $this->closure;
}
public function __destruct() {
echo $this->message . ' - ';
$this->getClosure()();
echo $this->endingMessage ? ' - ' . $this->endingMessage : '';
echo "\r\n";
}
}
function it($message, $closure) {
return new TestCase($message, $closure);
}
it('ok nice', function() {
echo 'what to do next?';
});//outputs: ok nice - what to do next?
it('ok fine', function() {
echo 'what should I do?';
})->addEndingMessage('THE END');//outputs: ok fine - what should I do? - THE END
I am writing a basic templating class for my own project. The basic usage is this:
$template = new Template('template_file.php');
$template->assignVariable('pageTitle', 'Home page');
$template->render();
Contents of 'template_file.php':
<?php print $pageTitle; ?>
This is what template class does step by step:
Stores variables in a private array when assignVariable method is called
When render method is called, extracts stored variables, includes template file in a ob_start() and ob_end_clean() block. Stores output in a variable with ob_get_contents() and then prints stored output.
I know this is a very simple templating class but works as expected. The question is should I delegate the including the template file to another class? I had this question when I was writing the unit tests for this class. I thought that file system interaction should be encapsulated. What do you think? If you think that it should not, how can I mock including a file in my tests?
Maybe I just pass the contents of the template file to the class like this:
$templateContent = file_get_contents('template_file.php');
$template = new Template($templateContent);
...
Edit: I decided to encapsulate the input process of template class for the sake of writing better unit tests and encapsulation. But as johannes pointed out, I needed to use eval() for that purpose which seemed not right. Johannes pointed me to the direction of stream wrappers for mocking the including in unit tests. But that inspired a new idea on me. Here is what I am going to do; I will continue to use include() in my template class but this time with stream wrappers. I will pass protocol handler to my template class while initializing it. This way I can create my own stream wrappers for fetching template data from database or using a local variable. Here are the examples:
$template = new Template('file://template_file.php');
stream_wrapper_register('database', 'My_Database_Stream');
$template = new Template('database://templates/3'); // templates table, row id 3
stream_wrapper_register('var', 'My_Var_Stream');
$myTemplate = '<?php print "Hello world!"; ?>';
$template = new Template('var://myTemplate');
I have already implement custom stream wrapper for local variables. Here it is:
class My_Var
{
protected $position;
protected $variable;
function stream_open($path, $mode, $options, &$openedPath) {
$url = parse_url($path);
global $$url['host'];
$this->variable = $$url['host'];
$this->position = 0;
return true;
}
public function stream_read($count) {
$ret = substr($this->variable, $this->position, $count);
$this->position = strlen($ret);
return $ret;
}
public function stream_eof() {
return $this->position >= strlen($this->variable);
}
}
stream_wrapper_register('var', 'My_Var');
$myvar = '<?php print "mert"; ?>';
include 'var://myvar';
exit;
I always liked the approach of this fellow:
http://www.massassi.com/php/articles/template_engines/
This approach takes advantage of the fact that PHP has started as a template engine. (The author also notes that it is silly to write a bloated template engine in PHP, when it is in fact itself a templating engine.) It might not really answer your question directly, but maybe it helps you.
By passing the contents using file_get_contents() and such you have to use eval() for execution which is bad in multiple ways. One of the most relevant here is that an opcode cache can't cache the file then. Doing an include('template_file.php'); let's APC or others cache the compiled script.
Irrespective of the evils of eval vs using a include, to answer your question, I'd have to agree and use a separate class to encapsulate the I/O aspect of your solution.
Whilst this might seem like overkill (as it will be in most instances), this is probably the only sane way to provide the isolation of control/dependency injection that you're after.
The question is should I delegate the including the template file to another class?
The question is, why not?