Need an advice for design pattern - php

I need an advice for my simple project. It's a logger system. I have the following files/classes
File - check if file exist is readable etc
ConfigParser - it's an abstract class of which I use the __construct method to do some things. The class is never instantiated directly. It's a decorator.
abstract class ConfigParser
{
protected $filename;
public function __construct($file)
{
// Here I want to invoke validate() method of File class
// I know that I can do $file = new File(); $file->validate()
// but the idea is to keep the things decoupled
// Also I know that I can extend the File class ConfigParser extends File
// but this doesn't make sence
// I can pass the File object on child class new XmlParser('file.xml', $fileObj)
// but this doesn't make sence too.
// I don't want to use traits as it's bizarre for me
}
}
XmlParser - extends ConfigParser
IniParser - extends ConfigParser
As the project goal is to keep the classes decoupled I can't figure out how to implement the File class in this scenario.

I don't think it's such a nice design to do the validation in the constructor. A constructor should simply create the Parser and possibly do simple things.
What you could do would be using the template method pattern, then do the validation in the parent class and delegate the real parsing to the actual parser class.
abstract class ConfigParser {
final function parse(){
$file->validate();
$this->conreteParse();
}
abstract function concreteParse();
}

Related

Is this a legitimate use of the Abstract Factory pattern?

Here's what I'm trying to implement in my program:
The program should open a zip file, which contains many data files
The format of the data files can differ between zip files (e.g. csv, tab delimited, or could even be some kind of binary file which needs decoding)
However, within a zip file all data files will be of the same type
I have been reading "Design Patterns" by Gamma et al., and have been looking at the Abstract Factory pattern to try to solve this.
Ideally, I want to have one class for the Zip file, which can read any type of data file within it. I guess I would have two classes - FileTypeA and FileTypeB, which could process different formats of data (although there could be more in the future). I would like a way of telling my ZipFile class which type of file to use when reading the data.
So far, this is what I have come up with:
<?php
/**
* An abstract factory used for creating data files of any type
*/
abstract class DataFileFactory{
abstract function createFile($id);
}
/**
* A factory for creating and setting up a data file of type 'A'
*/
class FileAFactory extends DataFileFactory{
public function createFile($id){
$file = new FileA();
$file->setSampleId($id);
return $file;
}
}
/**
* A factory for creating and setting up a data file of type 'B'
*/
class FileBFactory extends DataFileFactory{
public function createFile($id){
$file = new FileB();
$file->setSampleId($id);
return $file;
}
}
/**
* An abstract class which defines some functionality of a data file
*/
abstract class DataFile{
abstract function readData();
abstract function setSampleId();
}
/**
* Concrete class that processes a data file of type 'A'
*/
class FileA extends DataFile{
public function readData(){
echo "Reading data from a file A<br/>";
}
public function setSampleId(){
echo "Setting sample id of a file A<br/>";
}
}
/**
* Concrete class that processes a data file of type 'B'
*/
class FileB extends DataFile{
public function readData(){
echo "Reading data from a file B<br/>";
}
public function setSampleId(){
echo "Setting sample id of a file B<br/>";
}
}
/**
* Concrete class that reads a zip file and reads each file within the zip
*/
class ZipFile{
private $files = array("file1.txt","file2.txt","file3.txt","file4.txt");//this would be an array read from the zip file
private $sampleId = 1;//this would be derived from some other function
/**
* Read all the files in a zip archive.
* $factory can be an instance of any class that extends DataFileFactory, and is used for creating each file
*/
public function readFiles(DataFileFactory $factory){
foreach($this->files as $fileName){//loop through each file in the zip
$file = $factory->createFile($this->sampleId);//use the factory to create the desired file
$file->readData();//now read the data from the file!
echo "object created of type: ".get_class($file)."<hr/>";
}
}
}
/***********************************************************************************************
* IMPLEMENTATION
***********************************************************************************************/
$zip = new ZipFile();//create a new zip file
$factory = new FileAFactory();//instantiate a new factory, depending on which type of file you want to create
$zip->readFiles($factory);//read the files, passing the correct factory object to it
Can anyone tell me:
(A) Whether this is a good way of achieving what I'm looking for, or is there some simpler way of doing it?
(B) Is this actually the Abstract Factory pattern, or have I completely misunderstood?
Thanks in advance!
It's a good implementation but it can be finetuned a bit if you use interfaces.
An abtract class with all virtual methods it's just a interface so don't use abstract classes, use interfaces.
interface IDataFileFactory{
public function createFile($id);
}
class FileAFactory implements IDataFileFactory
class FileBFactory implements IDataFileFactory
If you find repeating code in FileAFactory and in FileBFactory methods then it is time to refactor your classes and create inheritance.
interface IDataFileFactory{
public function createFile($id);
}
abstract class BaseFileFactory implements IDataFileFactory {
//some methods implementation with common features to avoid repeating code
//some abstract methods to be implemented for A and B FileFactories
//absolute abstract base class has no sense because in php you can use interfaces.
//...
}
class FileAFactory extends BaseFileFactory
class FileBFactory extends BaseFileFactory
Then use throug interface:
public function readFiles(IDataFileFactory $factory){
//create a file using factory
return IDataFile; //return Interface implemented by all DataFile types.
}
You can do the same thing with DataFile base class and so on.
I also recomend to not pass factories in parameters because a factory is out of context. Try to do not mix architecture implementation with data and info process workflow. You can create a container, in a scope accesible for your other classes, to resolve the factory.
The container can, for example, read configuration files to create concrete factory in application bootstrap; read from some value, choosed by the user in previous steps of the user case, stored in a class instance or accepting a parameter in runtime to resolve the factory. It's about implement some kind of simple dependency inyection.
Anyway, this is only my point of view and can be a hurge amount disagreements.
I hope it help.

PHP design- abstract classes and factory methods

I am trying to work out the best way to design my classes and I think abstract classes it the right way here, but I'm not sure! I am building a plugin for Wordpress carts that at the moment, will work for both Woocommerce and WP-Ecommerce. As these two systems have different implementations of certain functionality, such as getting an order object, I want to create a separate class for each platform.
I have the following which will contain generic methods that should be available to the classes that inherit from it. This class should never be instantiated:
class Order_Export {
}
I then have 2 more classes that will inherit from the above:
class Order_WooExport extends Order_Export {
}
class Order_WPExport extends Order_Export{
}
Is my design right here? Am I right in saying the class Order_Export should be an abstract class? What about methods that I want the class inheriting to implement? Do I simply mark the signature in the abstract class and not provide a body, or do interfaces come into play somewhere here?
How about instantiating the right class? Do I create a factory that will return one or the other?
Any advice appreciated!
That sound correct to use abstract base class, as long as you are sure to never need to instantiate Order_Export :
abstract class Order_Export
{
abstract protected function someMeth1();
abstract protected function someMeth2();
public function someMeth3() {
// Do common thing to both Order_WooExport and Order_WPExport
// using someMeth1(), someMeth2()...
}
}
Then :
class Order_WooExport extends Order_Export
{
protected function someMeth1() {
// Do something specific
}
protected function someMeth2() {
// Do something specific
}
}
Finally, the factory seems to be the right way to go too.

Force child classes to override a particular function in PHP

I am creating a reporting library in PHP and developed an abstract class named ReportView. This will provide the basic functionality of a report like Generating header and footer, create parameter form.
There will be another function named generate_report in this class. Currently it is empty in abstract class as at this level we do not know the contents of report. Further it includes a render function which calls this generate_report function and sends output to browser.
So I need whenever a child class inherits from ReportView it must implement
the generate_report method otherwise PHP must give error. Is there any keyword or method through which we can enforce implemetation of a specific function.
Do the following:
abstract class ReportView {
abstract protected function generate_report();
// snip ...
}
class Report extends ReportView {
protected function generate_report() { /* snip */ }
}
Any class that extends ReportView and is not abstract must implement generate_report (and any other abstract function in its super classes for that matter).
Sounds like you’d be better off creating an interface, which would enforce you to define those methods in classes that then implement this interface.
<?php
interface ReportInterface {
public function generate();
}
class MyReportClass implements ReportInterface {
}
Instantiating MyReportClass here will throw a fatal error, telling you generate() has not been implemented.
Edit: You can also create abstract classes that implement this interface. You can have your abstract class contain any methods all extending classes need, and have your interface define any methods you need to be defined by extending classes.
You need to declare the method as abstract as well (and don't give it a method body), otherwise the derived classes will not be forced to implement it.
Alternatively, you could implement the method but have it just throw an Exception (not sure why you would want to do this).
Lastly, if all the methods in your base class are "abstract" (do not have bodies) then you can make the class into an Interface instead.

split extended classes over different files (php)

Szenario
I got a class as extend of an abstract class. The abstract class loads my files & extensions with their methods (link to pastebin for abstract class).
This gets called in my extends class like this (shortened & simplified - typos are only here at the Q-code):
class Pagination extends Pagination_Base
{
function __construct()
{
// loads the file "first.class.php" in the abstract class
parent::load_file( 'first' );
// stores the class as object in the abstract class, so we can access the methods and properties
parent::load_extension( new oxoFirst() );
}
}
Problem/Question
Now i got the error "Cannot redeclare class {$classname}".
I want to use my abstract class but still be able to move classes that contain extensions into separate files. Is there any way to do this?
Thanks in advance!
Use include_once instead of include in the load_file function.

Can php have an interface inside a class?

i would like to know if it is possible to have a function in PHP which returns an interface or a class which contains an interface?
i tried something like this, but it fails
<?php
//class for list of controllers for ACL
class Gestionale_Action_Helper_Crud extends Zend_Controller_Action_Helper_Abstract {
interface crud_controller
{
public function indexAction();
public function modificaAction();
public function cancellaAction();
public function creaAction();
}
public function getCrudInterface(){
return $this->crud_controller;
}
}
what i wanted to do, in zend framework, create an interface that crud controllers must implement, or even better if i could create an abstract controller and have them implement that
thank you
I'd suggest that you use Zend_Rest_Controller instead of creating your own interface.
Zend_Rest_Controller is an abstract class that defines five basic methods you need in a CRUD-controller: index, get, post, put, and delete.
Combined with Zend_Rest_Route it lets you create nice and clean RESTful application.
You can get more reading on Zend_Rest_Controller at http://weierophinney.net/matthew/archives/228-Building-RESTful-Services-with-Zend-Framework.html and http://techchorus.net/create-restful-applications-using-zend-framework
Just place the interface outside of any class (preferably in a different file) and let it be implemented by all your crud-controllers.
<?php
class GrudController implements CrudInterface
{
// ...
}
i'm not sure i get what it is you want to do, but i'm fairly certain you're asking the wrong question. if you simply want to make sure an object implements a certain interface, this is quite easy to do. lets say for example you have some helper method in a class which deals with a crud controller, you just specify the type in the argument list:
class crud_helper {
public function help(crud_controller $cc) {
$cc->indexAction();
}
}
now you can pass any object that is an instance of a class that implements crud_controller to the method help. but no other object.

Categories