Codeigniter and multiple inheritance - php

I've been using Codeigniter to construct the front end of a moderately sized application, and have run into an issue with--what I think may be--inheritance in PHP. Here is what I am trying to do:
In following the MVC architecture, I found that I was duplicating a lot of code across models, and decided to create a common Model from which other models could inherit. Simple enough. However, now, I am getting issues with some of the functions which are defined in the common Model class.
Here is a sketch of what I'm doing:
<?php
/**
* Common Model
*
*/
class DeviceModel extends Model {
function DeviceModel() {
parent::Model();
}
public function getDeviceId($d) { // this is just example code. }
public function getDeviceInfo($id) {
$selectStmt = "SELECT BLAH, BLAH2 FROM YADDAYADDA...";
$query = $this->db->query($selectStmt, array($id));
if ($query->num_rows() > 0) {
return $query->result();
}
}
}
?>
Here is the subclass:
<?php
require_once('devicemodel.php');
class ManageModel extends DeviceModel {
function ManageModel() {
parent::DeviceModel();
}
function getDropDownList($parkId,$tableName,$userclass) {
$arrCmds = array();
$arrHtml = array();
$deviceInfo = parent::getDeviceInfo($parkId);
$did = parent::getDeviceId($deviceInfo);
foreach ($deviceInfo as $device) {
$cmds = $this->getDeviceCommands($device->dtype,$tableName,$userclass);
array_push($arrCmds,$cmds);
}
//
// **After the refactor, I am receiving Undefined Offsets for this loop.**
//
for ($i=0; $i<sizeof($arrCmds); $i++) {
$html = $this->generateHtml($arrCmds[$i],$did[$i]);
array_push($arrHtml,$html);
}
return $arrHtml;
}
Is there a problem using multiple inheritance in codeigniter? I am fairly new to PHP and codeigniter.
Thanks for looking.

I don't see where is the multiple inheritance there.
I'm also working with codeigniter, and I had the need to subclass it's Controller so all my Controllers can descend from mine and not from CodeIgniter's directly.
CodeIgniter has native methods for extending it's classes with your own. Or you could open the model.php file (in system/libraries/) and at the top of the file, right after the if (!defined ...), you could add the code of your ManageModel class
Also here's a link for extending the model http://www.askaboutphp.com/50/codeigniter-extending-the-native-model-and-make-it-your-own.html

Related

Laravel Interface

Recently I came across interface from "Laravel 4 From Apprentice to Artisan" book with the example like this:
interface UserRepositoryInterface {
public function all();
}
class DbUserRepository implements UserRepositoryInterface {
public function all()
{
return User::all()->toArray();
}
}
What is interface? Where to put the interface file?
A Interface is a "contract" between itself and any class that implements the interface.
The contract states that any class that implements the interface should have all methods defined in the interface.
In this case DbUserRepository has to have a method named "all()" or a fatal error will occur when the class is instantiated.
The Interface file can be placed anywhere but the easiest is to put it in the same directory as the class that implements it.
The purpose of the interface is as follows:
Say you want to change your app from using a database (and Eloquent) and now instead you are going store data in JSON files and write your own methods for interacting with your JSON files. Now you can create a new repository e.g. JSONRepository and have it implement UserRepositoryInterface and because the interface forces you to define all the same methods that is defined in the interface, you can now be sure that your app will continue to work as it did. All this without you having to modify existing code.
The database example doesn't really make much real world sense to me because it is unlikely that I would change my storage system so drastically and the example always makes it seem like interfaces only have this one very small use case, which cant be further from the truth.
Coding to a interface has many benefits for you and your application.
Another example of interfaces in use can be:
Let's say you have a Calculator class and initially it has two operations it can perform (addition and multiplication). But a few weeks later you need to add another operation (e.g. subtraction), now normally this would mean you have to modify the calculator class and thus risk breaking it.
But if you are using a interface you can just create the Subtraction class and have it implement the CalculationInterface and now your app has a new operation without you touching existing code.
Example:
Calculator.php
<?php
class Calculator {
protected $result = null;
protected $numbers = [];
protected $calculation;
public function getResult()
{
return $this->result;
}
public function setNumbers()
{
$this->numbers = func_get_args();
}
public function setCalculation(CalculationInterface $calculation)
{
$this->calculation = $calculation;
}
public function calculate()
{
foreach ($this->numbers as $num)
{
$this->result = $this->calculation->run($num, $this->result);
}
return $this->result;
}
}
CalculationInterface.php
<?php
interface CalculationInterface {
public function run($num, $current);
}
Addition.php
<?php
class Addition implements CalculationInterface {
public function run($num, $current)
{
return $current + $num;
}
}
Multiplication.php
<?php
class Multiplication implements CalculationInterface {
public function run($num, $current)
{
/* if this is the first operation just return $num
so that we don't try to multiply $num with null */
if (is_null($current))
return $num;
return $current * $num;
}
}
Then to run the calculate method:
$this->calc = new Calculator;
$this->calc->setNumbers(5, 3, 7, 10);
$this->calc->setCalculation(new Addition);
$result = $this->calc->calculate(); //$result = 25
Now if you want to add a new operation let's say Subtraction you just create the Subtraction class and have it implement the CalculationInterface:
<?php
class Subtraction implements CalculationInterface {
public function run($num, $current)
{
/* if this is the first operation just return $num
so that we don't try to subtract from null */
if (is_null($current))
return $num;
return $current - $num;
}
}
Then to run it:
$this->calc = new Calculator;
$this->calc->setNumbers(30, 3, 7, 10);
$this->calc->setCalculation(new Subtraction);
$result = $this->calc->calculate(); //$result = 10
So in this example you are breaking your functionality up into smaller classes so that you can add, remove or even change them without breaking something else.

Write a Model Class in CodeIgniter with ORM style

I thought about using an actual ORM like Doctrine, then I figured its download link was even broken...and all tutorials online dated back to 2011. Also I'll have to write yaml files.
Then I start off by trying to write my own model class in ORM style.
I just fill it up with fields and save it to database, which is easy.
But I encounter a problem trying to retrieve data from database.
class User extends CI_Model {
public $id;
public $email;
public $displayName;
public function save() {
.....
}
public function search_by_email($email) {
$user = new User();
$this->db->select('email')->from('user')->where('email', $email);
$result = $this->db->get();
if ($result->num_rows()==0) {
return false;
}else {
foreach ($result->result() as $field) {
}
}
}
I know normally in CodeIgniter, you return $query->result(), well as ORM custom, I'm trying to return an object...Is there a way to do this? What function should I use?
result takes a string that represents a class that it will instantiate and assigned the result data (each field as a property of the object):
$query = $this->db->query("SELECT * FROM users;");
foreach ($query->result('User') as $row)
{
echo $row->name; // call attributes
echo $row->reverse_name(); // or methods defined on the 'User' class
}
regarding your comment, i'm pretty sure that codeigniter has no idea about anything regarding the class you pass to the result method. It looks like it just instantiates it and sets property and valuefor each column/value returned from the db:
$this->custom_result_object[$class_name][$i] = new $class_name();
foreach ($this->{$_data}[$i] as $key => $value)
{
$this->custom_result_object[$class_name][$i]->$key = $value;
}
One ORM that works quite well with codeIgniter is php-activerecord which is based off the rails active record model.
The function your trying to copy "search_by_email" is done through a
Late static binding method.
So you might see functions that are called like so:
Object::find_by_email()
Object::search_by_email()

Modular design pattern

I'm trying to decide the design of a system which is meant to allow for a high amount of extensiblity. From what I can tell, a pattern such as the abstract factory would not allow for overriding of the base methods, apart from duplicating code (as demonstrated below).
I've done some preliminary research into aspect oriented programming and it seems to be along the lines of what I'm looking for but I'm having a difficult time wrapping my head around the specifics.
abstract class Object {
protected $object_id;
protected $name;
function LoadObjectData()
{
$file_contents = readfile('object'.$object_id.'.data');
$data = array();
// parse file contents into $data array...
return $data;
}
function Create()
{
$data = $this->LoadObjectData();
$name = $data['name'];
return $data;
}
}
class User extends Object {
protected $email_address;
function Create()
{
$data = parent::Create();
$this->email_address = $data['email_address'];
return $data;
}
}
//----------Module 1-MySQL Lookup-------------
/*
* Redefine Object::LoadObjectData() as follows:
*/
function LoadObjectData()
{
$data = array();
$result = mysql_query("SELECT...");
// construct array from result set
return $data;
}
//----------Module 2-Cache Machine-------------
/*
* Redefine Object::LoadObjectData() as follows:
*/
function LoadObjectData()
{
if (exists_in_cache($object_id)) {
return get_cached_object($object_id);
}
$data = parent::LoadObjectData();
cache_object($object_id, $data);
return $data;
}
(This is sort of a poor example, but hopefully it helps to get my point across)
The intended system would have a very large proportion of methods available to be extended and I would like to minimize the extra effort and learning necessary for developers.
Is AOP exactly what I'm looking for, or is there a better way to deal with this?
Thanks!
So, you want to use a decorator pattern without defining the decorator itself.
If yes, then it's a monkeypatching and can be done with aspect-oriented tools. This can be solved easily with following extensions and frameworks:
PHP Runkit Extension
Go! Aspect-Oriented framework for PHP
PHP-AOP Extension.
You don't have to declare the base class as an abstract class. You can make it a regular class and have it load and instantiate other classes based on passed construct parameters. The constructor can return an instance of a class, not just the class the constructor is in. To avoid duplicating code, you can mix static with instantiated functions and variables. Just remember that a static function or variable is the same for ALL instances. Change a static variable in one and it is changed for all instances. A rather basic example of a plugin architecture.
class BaseObject {
protected static $cache = array();
public function __construct($load_plugin) {
require_once($load_plugin.'.class.php');
$object = new $load_plugin();
return $object;
}
public static function cacheData($cache_key, $data) {
self::$cache[$cache_key] = $data;
}
}
class Plugin extends BaseObject {
public function __construct() {
}
public function loadData() {
// Check the cache first
if ( !isset(self::$cache[$cache_key]) ) {
// Load the data into cache
$data = 'data to cache';
self::cacheData($cache_key, $data);
}
return self::$cache[$cache_key];
}
}

A PHP design pattern for the model part [PHP Zend Framework]

I have a PHP MVC application using Zend Framework. As presented in the quickstart, I use 3 layers for the model part :
Model (business logic)
Data mapper
Table data gateway (or data access object, i.e. one class per SQL table)
The model is UML designed and totally independent of the DB.
My problem is : I can't have multiple instances of the same "instance/record".
For example : if I get, for example, the user "Chuck Norris" with id=5, this will create a new model instance wich members will be filled by the data mapper (the data mapper query the table data gateway that query the DB). Then, if I change the name to "Duck Norras", don't save it in DB right away, and re-load the same user in another variable, I have "synchronisation" problems... (different instances for the same "record")
Right now, I use the Multiton / Identity Map pattern : like Singleton, but multiple instances indexed by a key (wich is the user ID in our example). But this is complicating my developpement a lot, and my testings too.
How to do it right ?
Identity Map
Edit
In response to this comment:
If I have a "select * from X", how can I skip getting the already loaded records ?
You can't in the query itself, but you can in the logic that loads the rows into entity objects. In pseudo-code:
class Person {}
class PersonMapper {
protected $identity_map = array();
function load($row) {
if (!isset($this->identity_map[$row['id']])) {
$person = new Person();
foreach ($row as $key => $value) {
$person->$key = $value;
}
$this->identity_map[$row['id']] = $person;
}
return $this->identity_map[$row['id']];
}
}
class MappingIterator {
function __construct($resultset, $mapper) {
$this->resultset = $resultset;
$this->mapper = $mapper;
}
function next() {
$row = next($this->resultset);
if ($row) {
return $this->mapper->load($row);
}
}
}
In practice, you'd probably want your MappingIterator to implement Iterator, but I skipped it for brevity.
Keep all loaded model instances in "live model pool". When you load/query a model, first check if it has been already loaded into pool (use primary key or similar concept). If so, return the object (or a reference) from pool. This way all your references point to the same object. My terminology may be incorrect but hopefully you get the idea. Basically the pool acts as a cache between business logic and database.
Multiton
Best option if you want to use a variety of singletons in your project.
<?php
abstract class FactoryAbstract {
protected static $instances = array();
public static function getInstance() {
$className = static::getClassName();
if (!(self::$instances[$className] instanceof $className)) {
self::$instances[$className] = new $className();
}
return self::$instances[$className];
}
public static function removeInstance() {
$className = static::getClassName();
if (array_key_exists($className, self::$instances)) {
unset(self::$instances[$className]);
}
}
final protected static function getClassName() {
return get_called_class();
}
protected function __construct() { }
final protected function __clone() { }
}
abstract class Factory extends FactoryAbstract {
final public static function getInstance() {
return parent::getInstance();
}
final public static function removeInstance() {
parent::removeInstance();
}
}
// using:
class FirstProduct extends Factory {
public $a = [];
}
class SecondProduct extends FirstProduct {
}
FirstProduct::getInstance()->a[] = 1;
SecondProduct::getInstance()->a[] = 2;
FirstProduct::getInstance()->a[] = 3;
SecondProduct::getInstance()->a[] = 4;
print_r(FirstProduct::getInstance()->a);
// array(1, 3)
print_r(SecondProduct::getInstance()->a);
// array(2, 4)

strategies for managing long class files in php

I've got a bunch of functions that I want to move into a class. They're currently split into a couple of fairly long files. I'd prefer not to have one 2500 line file, but as far as I can tell, you can't use include to split a class up into multiple files. In theory, I could group the functions in different classes, but they're closely related enough that I feel like they belong together, and splitting them will reduce some of the utility that I'm hoping to get from moving away from a procedural approach (with shared properties, rather than a bunch of parameters that are in nearly every function).
I know this is a bit vague, but any suggestions/pointers? If it matters, this is for a prototype, so ease of code management takes precedence over security and performance.
UPDATE: Let me see if I can remove some of the vagueness:
This class/set of functions outputs the html for a complex form. There are many different sections and variations within each section, depending on about 5 or 6 parameters, which are currently passed into the functions. I was hoping to define the parameters once as properties of the class and then have access to them from within all of the section-creation methods. If I use sub-classes, the values of those properties won't be initialized properly, hence the desire for one class. (Hmm... unless I define them as static. I may have just answered my own question. I'll have to look to see if there's any reason that wouldn't work.)
I've currently got a mess of functions like:
get_section_A ($type='foo', $mode='bar', $read_only=false, $values_array=array()) {
if ($this->type == 'foo') { }
else ($this->type == 'foo') { }
}
So I was initially imagining something like:
class MyForm {
public $type; // or maybe they'd be private or
public $mode; // I'd use getters and setters
public $read_only; // let's not get distracted by that :)
public $values_array;
// etc.
function __constructor ($type='foo', $mode='bar', $read_only=false, $values_array=array()) {
$this->type = $type;
// etc.
}
function get_sections () {
$result = $this->get_section_A();
$result .= $this->get_section_B();
$result .= $this->get_section_C();
}
function get_section_A() {
if ($this->type == 'foo') { }
else { }
}
function get_section_B() {}
function get_section_C() {}
// etc. for 2500 lines
}
Now I'm thinking something like:
// container class file
class MyForm {
static $type
static $mode
static $read_only
static $values_array
// etc.
function __constructor ($type='foo', $mode='bar', $read_only=false, $values_array=array()) {
MyForm::$type = $type;
// etc.
}
function get_sections () {
$result = new SectionA();
$result .= new SectionB();
$result .= new SectionC();
}
}
// section A file
class SectionA extends MyForm {
function __constructor() {
if (MyForm::$type == 'foo') { }
else { }
}
function __toString() {
// return string representation of section
}
}
// etc.
Or probably I need an abstract class of FormSection where the properties live.
Any other ideas/approaches?
I'd split them up into as many classes as you want (or as many that make sense) and then define an autoloader to obviate inclusion headaches.
EDIT
Ok, after seeing more of your code - I think you're approaching subclasses wrong. You have lots of if statements against $type, which signals to me that that is what the polymorphism should be based on.
abstract class MyForm
{
protected
$mode
, $read_only
, $values
;
public function __construct( $mode, $read_only=false, array $values = array() )
{
$this->mode = $mode;
$this->read_only = (boolean)$read_only;
$this->values = $values;
}
abstract function get_section_A();
abstract function get_section_B();
abstract function get_section_C();
// final only if you don't want subclasses to override
final public function get_sections()
{
return $this->get_section_A()
. $this->get_section_B()
. $this->get_section_C()
;
}
}
class FooForm extends MyForm
{
public function get_section_A()
{
// whatever
}
public function get_section_B()
{
// whatever
}
public function get_section_C()
{
// whatever
}
}
Usually I do something like this:
class one
{
public function __get($key)
{
// require __DIR__ / $key . php
// instanciate the sub class
}
public function mainMethod()
{
}
}
class one_subOne extends one
{
public function otherMethod()
{
}
}
class one_subTwo extends one
{
public function anotherMethod()
{
}
}
$one->mainMethod();
$one->subOne->otherMethod();
$one->subTwo->anotherMethod();
As far as building the view is concerned, you might like to try the CompositeView pattern.
Here's a small example of how it could look in PHP. Pretend, for the sake of this example, that View::$html is encapsulated in a Template class that can load html from disk and allows you to inject variables, handles output escaping, etc.
interface IView {
public function display();
}
class View implements IView {
public $html = '';
public function display() {
echo $this->html;
}
}
class CompositeView implements IView {
private $views;
public function addPartial(IView $view) {
$this->views[] = $view;
}
public function display() {
foreach ($this->views as $view) {
$view->display();
}
}
}
The reason for the IView interface is to allow you to build composite views with other composite views.
So now consider a form with three parts: header, body and footer.
class HeaderView extends View {
public function __construct() {
$this->html .= "<h1>Hi</h1>\n";
}
}
class BodyView extends View {
public function __construct() {
$this->html .= "<p>Hi there.</p>\n";
}
}
class FooterView extends View {
public function __construct() {
$this->html .= "<h3>© 2012</h3>\n";
}
}
(Again, you wouldn't just write HTML into that public variable and handle output escaping yourself. You'd likely reference a template filename and register your data via the template's interface.)
Then, to put it all together you would go:
$view = new CompositeView();
// here you would make decisions about which pieces to include, based
// on your business logic. see note below.
$view->addPartial(new HeaderView());
$view->addPartial(new BodyView());
$view->addPartial(new FooterView());
$view->display();
So now your views can be composed and the fragments reused, but you can easily make a mess with the code that builds them, especially if you have a lot of conditions and many different possible outcomes (which it sounds like you do.) In that case, the Strategy pattern will probably be of some help.
If you haven't already read UncleBob's SOLID article, do it before anything else! At least the Single Responsibility Principle. I would also recommend reading Refactoring to Patterns by Joshua Kerievsky at some point.
If you want to do OOP, separate the concerns and encapsulate them into appropriate classes. Combine them either by extending them or by composition or better aggregation. Remove any duplicate code. Dont repeat yourself.
In your case, separate the stuff that is about any Form from the stuff that is about your specific form. The code that can be used for any Form is the code you want to place into a generic Form class. You can reuse this in later projects. For an example of a very complex Form class, check out Zend_Form.
Anything in your code related to the/a specific form gets into a class of it's own that extends the generic form. Assuming from the type property given in your code, you might end up with multiple special purpose form classes (instead of one-type-fits-all-form), which will likely eliminate the complexity from the getSection methods and make your code a lot easier to maintain because you can concentrate on what a specific type of form is supposed to look like and do.
Lastly, if you got code in there that fetches data for the form from within the form or is otherwise not directly related to form building, remove it and make it into a separate class. Remember, you want to separate concerns and your form classes' concern is to build a form, not get it's data or something. Data is something you will want to pass to the form through the constructor or a dedicated setter.
They are all in different files, which means that they were different enough to group by file. Just take the same logic when building them into classes. I have a Page object that deals with building the page. Technically the HTML for my page header is part of the page, but I separate it into a Page_HTML class for maintaining my sanity and not creating gigantic classes.
Also, I tend to make the sub_classes, like Page_HTML in this case, static, instead of instantiating it. That way I can access the $this variables in the Page class, but still group it into another class.
class Page
{
function buildPage($content)
{
$content = Page_HTML::getHeader() . $content;
}
}
class Page_HTML
{
function getHeader()
{
}
}
This class/set of functions outputs
the html for a complex form.
Why not remove PHP from the equation? It seems you're using PHP to organize views which can be done easily with the filesystem. Just write the views in HTML with as little PHP as possible. Then use PHP to map requests to views. I'm assuming you're processing forms with PHP, and you could continue to do so. However, your classes will become much smaller because they're only accepting, verifying and presumably saving input.

Categories