I was wondering what should I do with my entities? For example, a class named Articles, with a few datamembers (name/title/date) and getters & setters. I could add these to my Articles datamember, but it's better practice to seperate those. So what do you think?
Thanks!
i usually do this:
1.- create my entity classes in /system/application/classes
class MyEntity {
}
2.- define a constant to point to that folder on /system/application/config/constants.php
define('CLASSES_DIR', APPPATH . "classes/");
3.- include the entities classes from the models:
require_once(CLASSES_DIR . "MyEntity.php");
class MyModel extends Model {
function test() {
$entity = new MyEntity();
$entity->doSomeStuff();
}
}
That won't break your mvc structure, and keeps for entities classes separated. Hope that helps!
I liked #ilbesculpi's solution, but I customized it a bit using a namespace rather than using a constant and require_once. Here is my version:
1) Create my entity classes in /system/application/entities.
namespace MyApplication\Entities;
class ArticlesEntity
{
function doSomeStuff()
{
// Your code here...
}
}
2) Include my entity class in my model via a using statement.
use MyApplication\Entities\ArticlesEntity;
class ArticlesModel extends CI_Model
{
function test()
{
$entity = new ArticlesEntity();
$ArticlesEntity->doSomeStuff();
}
}
CodeIgniter models use the singleton pattern. You can create libraries or use $foo = new Some_Model if you like, remember that its all just PHP :)
Related
I am developing an app that has two name spaced differentiated folders.
Lets say
App/Http/Users/ and
App/Http/Drivers/
I have two api routes setup api.php and dapi.php.
The routes are also prefixed by localhost/api/foo and localhost/dapi/bar respectively.
Everything works ok but the issue is that there are some methods that I need to call for both. Such as save address info or call. Right now I have to make same controllers for both and duplicate a lot of code. What would be the best approach for this kind of project?
you should use traits
Traits are a mechanism for code reuse in single inheritance languages
such as PHP. A Trait is intended to reduce some limitations of single
inheritance by enabling a developer to reuse sets of methods freely in
several independent classes living in different class hierarchies. The
semantics of the combination of Traits and classes is defined in a way
which reduces complexity, and avoids the typical problems associated
with multiple inheritance and Mixins.
for example:
in your traite:
trait SameMethods {
function call() { /*1*/ }
function saveAddress() { /*2*/ }
}
.
namespace App\Http\Drivers;
class Foo extends Controller{
use SameMethods ;
/* ... */
}
.
namespace App\Http\Users;
class Bar extends Controller{
use SameMethods ;
/* ... */
}
Now you have these methods on your controllers.
another way is you have an another class for example ParentController extended from Controller that it contains same methods and foo and bar extends from this class
ParentController extends Controller {
function call() { /*1*/ }
function saveAddress() { /*2*/ }
}
.
namespace App\Http\Drivers;
class Foo extends ParentController {
/* ... */
}
.
namespace App\Http\Users;
class Bar extends ParentController {
/* ... */
}
I have an abstract question for you.
Question:
How can a subclass that extends an abstract class register itself to the abstract class or another class?
Problem:
Guess we have a module master named ModuleMaster and maybe someone else writes another modules to handle a specific problem without modifying the master class and named it ModuleA. For that reason we want to implement a dynamic loading of problem solutions.
My idea:
File: Extensions.php:
namespace Project\Extensions;
class Extensions
{
public function getLoadedModules()
{
var_dump(ModuleMaster::LOADED_MODULES);
}
}
File: Modules\ModuleMaster.php:
namespace Project\Extensions\Modules;
abtract class ModuleMaster
{
public const LOADED_MODULES = array();
}
File: Modules\ModuleA.php:
namespace Project\Extensions\Modules;
class ModuleA extends ModuleMaster
{
}
I hope you understand what I mean and can help with that abstract problem.
This is very strange to use. It's probably a better design to have an external registry for your module. But I think you're asking for this:
File: Extensions.php:
namespace Project\Extensions;
use \Project\Extensions\Modules\ModuleMaster;
class Extensions
{
public function getLoadedModules()
{
var_dump(ModuleMaster::getLoadedModules());
}
}
File: Modules\ModuleMaster.php:
namespace Project\Extensions\Modules;
abstract class ModuleMaster
{
public static function getLoadedModules() {
$parent = self::class;
return array_values(array_filter(\get_declared_classes(), function ($class) use ($parent) {
return in_array($parent, class_parents($class));
}));
}
}
File: Modules\ModuleA.php:
namespace Project\Extensions\Modules;
use \Project\Extensions\Modules\ModuleMaster;
class ModuleA extends ModuleMaster
{
}
Example use:
$e = new \Project\Extensions\Extensions;
$e->getLoadedModules();
Example result:
array(1) {
[0]=>
string(34) "Project\Extensions\Modules\ModuleA"
}
Please note that the code only works if all your class files are included into the context before running getLoadedModules(). PHP won't know your class exists if it is not already loaded into the context.
You seem to be trying to create a capability in the parent class which is not required or inappropriate in the child class. This is the opposite of inheritance and hence an anti-pattern. Further, even though it might be considered as an extension of reflection, you are trying to put runtime data in a class - that's not what classes are for.
You've also not explained in any way that I can understand why you want to do this.
I suspect you really want to implement a factory, strategy or a registry object.
This is a follow-up to my previous question about resolving the diamond issue in php.
As I state in that question, I resolve my problem by using traits and passing the instance of the class to the method of the trait. Such as:
trait SecurityTrait
{
public function beforeExecuteRouteTrait($controller, Dispatcher $dispatcher)
{
// Do something that makes use of methods/members of the controller
}
}
class AppController extends Controller
{
use SecurityTrait;
public function beforeExecuteRoute(Dispatcher $dispatcher)
{
return $this->beforeExecuteRouteTrait($this, $dispatcher);
}
}
However, I am still uncomfortable with this as I don't think this is how traits are really supposed to be used. In my reading I haven't found any way in which to access class members in traits (make $this inside a trait refer to the class using it). Is this possible? Or is there another way to implement a similar behaviour?
After reading some of the answers...
Previously I thought I had received errors when using $this->... inside the trait and this led me to believe the trait could not access anything to do with the underlying class. After reading the answers I tried altering my code to use $this->... inside a trait again and it works - which means a typo several weeks ago has given me far too much headache...
The example given previously now looks like this
trait SecurityTrait
{
public function beforeExecuteRoute(Dispatcher $dispatcher)
{
// Do something that makes use of methods/members of the controller
}
}
class AppController extends Controller
{
use SecurityTrait;
}
Much cleaner and more easily understandable but provides the same functionality.
If you use a trait inside a class then that trait has full access to all class's members and vice versa - you can call private trait methods from the class itself.
Think of traits as code that literally gets copy/pasted into the class body.
For example:
trait Helper
{
public function getName()
{
return $this->name;
}
private function getClassName()
{
return get_class($this);
}
}
class Example
{
use Helper;
private $name = 'example';
public function callPrivateMethod()
{
// call a private method on a trait
return $this->getClassName();
}
}
$e = new Example();
print $e->getName(); // results in "example"
print $e->callPrivateMethod(); // results in "Example"
In my view referencing classes in traits is not the best way to use them but there's nothing stopping anyone from doing it.
No, that's exactly what Traits are for. Your class already extends a class so you can't inherit the methods and variables of any other classes.
Think of a Trait like copy/paste for code execution. When a class includes a Trait, it's just as if you had written all that code into the class itself.
I got this problem I have a method that is repetitive in all the Repositories, for example this method.
function getAllOrderedBy($column) {
$qb = $this->createQueryBuilder('ac')
->select('ac')
->orderBy('ac.' . $column);
return $qb->getQuery()->getResult();
}
I want to extract it in another superclass, OrderedRepository for example and use it as the base class for all the other repositories.
Now the problem is how to do that ?
I tried to instantiate EntityRepository in the constructor of the OrderedRepository,
something like this, but also instantiating there all the internal objects, needed for other stuff, but it didn't really worked, and I felt it is the wrong path to follow.
function __construct() {
parent::__construct();
$this->blabla_option = "instantiated";
}
Could you please give an example of correct extending of EntityRepository so than this extended class could serve as a base class for other repositories ?
P.S. I'm a begginer in PHP so please excuse me if I hurt your feelings with my unawareness.
This is more a Doctrine2 thing.
Assuming you are using annotations for your doctrine mapping, you have to declare which repository class you are using in the Entity:
/**
* #ORM\Entity(repositoryClass="Fully\Qualified\Namespace\To\MyRepository")
*/
class MyEntity { }
as explained here: http://symfony.com/doc/2.0/book/doctrine.html#custom-repository-classes .
Then, you can code this custom MyRepository class, using standard class inheritance.
You could imagine something like that:
class OrderedRepository extends EntityRepository
{
// some extra methods...
}
class MyRepository extends OrderedRespository {}
Finally, if you want to override the __constructor of your repository, you have to initailize the parent constructor with the same arguments:
public function __construct($em, Mapping\ClassMetadata $class)
{
parent::__construct($em, $class);
// some extra stuff
}
I know it is not a good experience. But just I want to know it is possible to access a function from model or controller class from a helper file in codeigniter.
cant you use something like this i believe.
$Helper =& load_class('Helper'); //Load the (Helper Loader) $this->load->helper becomes $helper
$Class = $Helper('Name of class');
But i do not see why you should do this
Can't you just create an extra model class like
class DBFile
{
...
}
then create your Model
class Model_SomeName extends DBFile
{
/*So no this uses DBFile instead of CI_Database or w.e it is*/
}
Yes, that is possible, you will have to load the helper class first like this:
$this->load->helper('name of helper class');
More Info:
http://codeigniter.com/user_guide/helpers/array_helper.html