Using a model inside a helper - php

I've a quick question related to the software architecure. In my application I have a model which contains a method to check the environment the application works in. Let's say the model is called "AppModel".
So, the AppModel::isDevEnv() indicates whether the app is runnig in production or development. It's easy to call this method inside others models, components etc.
The problem is when I want to check the environement inside a view. I created a helper with a propriety method inside just to cover the method from the model and return the result coming from exactly model's method.
class AppModel {
public function isDevEnv() {
return boolean;
}
}
class AppHelper {
public static function isDevEnv() {
$app = new AppModel();
return $app->isDevEnv();
}
}
Is it correct approach? Maybe it's a little bit overcomplicated? Maybe I should just make a static method inside a model and call it whenever I would like to call it?

If this is a legacy system I would recommend to refactor it to the desirable solution. If you want to have this helper or it is a required step for further refactoring then do it.
In general I would inject services which behave differently based on the environment instead of checking the environment inside your models. But it might not be easy with legacy system.

Related

PHP MVC - Model needs to access data from another model

I have built a small PHP MVC framework and just want to clarify the best way to get data from one model into another. For example:
I have a Users_model that contains a method called get_users().
I also have Communications_model that needs to get specific or all user data and as such needs to access the get_users() method from the Users_model.
Is it best practice to:
a) Instantiate the Users_model in a controller and pass the data from the get_users() method into the Communications_model?
b) Instantiate the Users_model inside the Communications_model and run get_users() from there, so it can be accessed directly?
c) Another way?
Many thanks for any help.
It depends of your motive behind this.
If you want effect on result, then using well know library, like Doctrine etc. should be your choice.
If you want to learn design patterns, then you should get read about ActiveRecord or DataMapper + Repository patterns. Then implements both and check out.
If you want your code, this way - ORM should represent relations of data, then you should ask what it more important? If you menage communication (bus, train), then user can be there assigned and getting users from communication is OK. If user have communication (like car), then relation is reversed.
All depends, what is you motive behind this. Using library, like Doctrine, could you help you running you application. If you want learn design patterns, then check out both options to get some experience.
What you call "users model" is a repository. And what you call "communication model" looks like a service.
Your communication service should have the user repository passed in constructor as a dependency.
I honestly think, that a huge part of your confusion is that you try to call all of those things "models". Those classes are not part of the same layer. You migth find this answer to be useful.
All are possible ways but what I usually do is, whenever there is any function that I think would be reused a number of times by a number of objects, I declare it as static.
It would save the effort of playing with object declaration and would be easily accessible by ClassName::function();
Again, it's a design choice, usually objects are declared right there in the controller and used as per the need but just to save declaration of objects again and again I follow the approach of declaring function static.
The simple principle here is using the __construct() (constructor) to build the object with the relevant properties from the Database. The User Model will have a static function (therefore accessible through any scope) to create an array of instanced objects by simply passing the model data through a new self() which returns the instance.
The concept is you end up with an array of User_Model instances each being a build of the Database columns to properties. All that's left is to create the Database Model and the functions to retrieve the columns and data.
class Communications_Model {
private $_all_users;
public function getUsers() {
$this->_all_users = Users_Model::loadAllUsers();
}
}
class Users_Model {
private $_example_property;
public function __construct($user_id) {
$data = SomeDatabaseModel::getConnection()->loadUserFromDatabase((int)$user_id);
$this->_example_property = $data['example_column'];
}
public static function loadAllUsers() {
$users = array();
foreach(SomeDataModel::getConnection()->loadAllUsers() as $data) {
$users[] = new self($data['user_id']);
}
return $users;
}
}
Of course, now, you have a $_all_users; property that has an array of instanced User Models containing the data.

yii2 - can someone explain the meaning of parent::init(); statement

I have looked online for the meaning of parent::init(); . All I was able to find was that init() is to initialize some settings which want to be present every time the application runs.
Can anyone please explain the meaning of parent::init() in exact sense, like significance of both the words?
Thanks in advance.( I am sorry if its too simple! )
When we use parent::init(), we are just calling the parent method (in this case init()) inside a method of the current class.
About parent::
For example, let's say we have a class called MyClass. This class have a awesome method that runs alot of things:
class MyClass
{
public function runStuffs()
{
// trigger events, configure external stuff, adding default values to properties.
}
}
Now, after some time, we decided to create a new Class that extends from the first one. And we called MySecondClass:
class MySecondClass extends MyClass
{
}
It already have the method runStuffs(), but, for this second class, we need to do more things in this method, but maintaining what it have.
Sure we could rewrite the whole method and just copy and paste what we have in MyClass and add the new content. But this isn't elegant or even a good practice. what if later on We change the method in MyClass, you probably would like that MysecondClass have that changes too.
So, to solve that problem, we can call the parent method before write your new content:
class MySecondClass extends MyClass
{
public function runStuffs()
{
parent::runStuffs();
// do more things!
}
}
Now MySecondClass->runStuffs() will always do what its parent do and, after that, more stuff.
About the init() method.
init() is a method used in almost all classes from Yii2 framework (since most of then extends from yii\base\Object at some point) and works just like the __constructor() method (native from PHP). But there is some differences, you can read more here.
Actually the init() method is called inside the __constructor(), and the framework encorage us to use init() instead of __construct() whenever is possible.
Now if both are pretty much the same thing, why do they create this method? There is an answer for that here. (take a look at qiang's answer, from the dev team):
One of the reasons for init() is about life cycles of an object (or a component to be exact).
With an init() method, it is possible to configure an object after it is instantiated while before fully initialized. For example, an application component could be configured using app config. If you override its init() method, you will be sure that the configuration is applied and you can safely to check if everything is ready. Similar thing happens to a widget and other configurable components.
Even if init() is called within constructor rather than by another object, it has meaning. For example, in CApplication, there are preInit() and init(). They set up the life cycles of an application and may be overridden so that the customization only occurs at expected life cycles.
Conclusion
So, when you use a init() method and calls parent::init() you are just saying you want to add more things to that method without removing what it already was doing.
The parent::init(); Method is useful to execute a code before every controller and action,
With an init() method, it is possible to configure an object after it is instantiated while before fully initialized.
For example, an application component could be configured using app config.
If you override its init() method, you will be sure that the configuration is applied and you can safely to check if everything is ready.
Similar thing happens to a widget and other configurable components.
In Yii, init() method means that an object is already fully configured and some additional initialization work should be done in this method.
For More Information check this link :
https://stackoverflow.com/questions/27180059/execute-my-code-before-any-action-of-any-controller
Execute my code before any action of any controller
might be helpful to you.

Why do I need the Init function in my Controller?

I am new to PHP and I have a few questions that follows:
Do I need the init function or can I do the job (whatever I need to do in my code) without the init function?
I am saying this because the NetBeans "kinda" created/added automatically the init() function in my project.
In my code I am suppose to create the CRUD functionality in it.
If I don't use it what's the problems I might have and the downsides?
As the official docs would say:
The init() method is primarily intended for extending the constructor. Typically, your constructor should simply set object state, and not perform much logic. This might include initializing resources used in the controller (such as models, configuration objects, etc.), or assigning values retrieved from the front controller, bootstrap, or a registry.
You can have controllers that don't override the init() method, but it will be called under the sheets anyways.
If you are new to PHP, do not start by using a framework. Instead you should learn the language itself.
There is nothing significant about init() function. It is not a requirement for classes in PHP. Hell .. even __construct() is not mandatory in PHP.
That said, Zend Framework executes it right after the controller is created. It is required if you are using ZF.
You can read more about it here.
init() in Zend_Framework for most practical purposes is where you would put code that you need to affect all of the actions in that controller.(at least to test against all of the actions).
For example I often use the init() method to set up the the flashmessenger helper and to set the session namespace I want to be used.:
public function init() {
if ($this->_helper->FlashMessenger->hasMessages()) {
$this->view->messages = $this->_helper->FlashMessenger->getMessages();
}
//set the session namespace to property for easier access
$this->_session = new Zend_Session_Namespace('location');
}
Also Netbeans did not make this method or the controller, Zend_Tool made the controller and the methods utilizing the interface that Netbeans provided. That's why in your PHP settings for Netbeans you have to provide the path to the ZF.bat file and click the register provider button if you change your ZF install.
One more thing...Be aware that there more methods available to the controller that provide hooks into different parts of the dispatch cycle. You may not need them very often but you need to know they are there.
Simply its a constructor for that class(controller)...
init(){
$this->a = 1; //If we set something like this in the init
}
public function fooAction(){
echo $this->a; //1
}
public function barAction(){
echo $this->a; //1
}
ie the variables,objects..that is initialised in init will be available to all the actions in that controller

MVC - Can I call more than one (or multiple) controller in class controller?

For projects written in php, can I call more than one (or multiple) controller in class controller? Example in http://img192.imageshack.us/img192/7538/mvc03.gif
ASK: I need to call an action from another controller... And if I do like the picture above, I'm being out-ethics?
Thanks,
Vinicius.
I'm sure that you can do what you want with whichever framework you're using. If you can't do it natively for whatever reason, then you can extend your framework as required.
Having said that, I personally don't like the idea of a controller calling another controller. It seems to somewhat break the MVC paradigm if only from a theoretical standpoint. What I might do instead is build a library class that contains the functionality required and then have both controllers instantiate that class as a member and call the functions required.
For example, using CodeIgniter:
libraries/MyLib.php:
class MyLib
{
public function MyFunc()
{ /* do whatever */ }
}
controllers/ControllerA.php:
class ControllerA extends Controller
{
public function index()
{
$this->load->library('MyLib');
$this->mylib->MyFunc();
}
}
controllers/ControllerB:
class ControllerB extends Controller
{
public function index()
{
$this->load->library('MyLib');
$this->mylib->MyFunc();
}
}
out-ethics? Anywhose... back to reality.
Yes, a controller can call another controller's action. For instance, in cakePHP, this functionality is afforded via requestAction
// pass uri to request action and receive vars back
$ot3 = $this->requestAction('/stories/xenu');
If you're rolling your own, the details of how to implement it will be very specific to your framework.
then you need to modify framework, find place where controller is lounched and add there your second controller.
what framework you are using?
You can do it any way that you want. You don't have to use MVC if you don't want to. However, in MVC you really should only have one controller active at a time. You probably want multiple Views or Models, not another Controller. There is nothing at all wrong in loading, say, a header and footer view for the menu and footer of the site.
If you are building another Controller, then feel that you need to access the functionality of a previous Controller to access its functionality (because it works with a specific / desired Model), then the Model you developed for the latter probably needs to be refactored. IN plain speak, your target Model may be doing too much. Break it up.
You are trying to avoid repeating yourself (DRY) by using calling the methods of a Controller that has already been developed, but in doing so your are creating TIGHT coupling between both controllers! If something changes in the borrowed controller, it will have an effect on the borrowing controller. Not good, Dr. Jones.

CodeIgniter: Where should a particular functionality go?

Here is a quick overview of the controllers functionality in most of the application:
controller loads a specific model, gets data from it, formats the data and passes the formatted data to the view.
Now there is a search page, which needs to do a search query over entire database (all models). It needs to show each type of data in its particular formatted output on a single page as a list.
The problem:
The search controller can do the search, dynamically load model for each record type, and get the data from model. Problem comes when the data needs to be formatted. I am trying to load the specific controller from the search controller, which is causing problems.
What to do?
PS: I tried using the 'Wick' library, but it fails when the controller's format function tries to use its own model and session object, giving errors about call to a member on a non-object.
After much refactoring and trial/error, It appears that the best way to achieve the above is this way:
Keep the format function in the base controller from which all other controllers are derived. The format options are passed to the function along with the data object as arguments.
Make a static function in each derived controller, which returns the formatting options of the data.
Inside the search controller (which is itself derived from the base controller), for each data object, call the static function of its particular controller which returns the data formatting options, then use that to format the object for the view.
I guess I can say I will stick to using the model only for interaction with the database, and let everything else be done by controller. If anyone has a better solution still, I am all ears.
It sounds like you want to use the Factory design pattern
Make this a library:
class MyModelFactory {
static public function Factory($data) {
$type = key($data);
return new $type($data);
}
}
now, in your controller, you can do something like this:
$model = MyModelFactory::Factory(array($_REQUEST['model'] => $_REQUEST));
and now you have an object of whatever model was specified in $_REQUEST['model']. Be sure to take any security precautions you may need for your application to assure the user has permissions to use the model that they request
Now, since you want to be using common methods and stuff, your models should probably be based off an abstract class / interface.. so instead of
class MyModelOne extends Model {
// stuff
}
You probably want something like this, to ensure your required methods will always be available:
abstract class MyAbstractModel extends Model {
protected $search_params;
public function __construct($data = array()) {
$search_params = $data['search_params'];
}
protected function GetSearchParameters() {
return $this->search_params;
}
abstract public function GetData();
abstract public function GetColumns();
abstract public function DefineViewOptions();
}
class MyModelOne extends MyAbstractModel {
public function GetData() {
$params = array();
$params[] = $this->db->escape_str($this->GetSearchParameters());
// return whatever data you want, given the search parameter(s)
}
public function GetColumns() {
// return some columns
}
public function DefineViewOptions() {
// return some configuration options
}
}
In general you can't load another controller from within a controller in CodeIgniter (although there are mods that allow you to do something like this).
I would try creating a class for formatting your data and add it to the application/library folder. Then load, use and re-use this class throughout your various controllers.
Here is a page from the CodeIgniter documentation Creating Your Own Libraries that explains the details and conventions.
Also, if a class is overkill, creating helper functions is an even lighter approach.
The difference between libraries and helpers in CodeIgniter is that libraries are classes, helpers are just a group of php functions.
Once you have formatted your data, you can load any view from any controller, so you should still have all the re-usability you need so you DRY (don't repeat yourself)
There are a few simple approaches based on the principle of what's simpler (versus what's perfectly DRY). Here's one alternative approach I use with CodeIgniter:
Instead of trying to load multiple controllers, reuse the view fragments from your search controller (or search route, depending which you're using). This requires using the same naming conventions for your data elements so the views are interchangeable, but you should be doing this anyway.
Instead of using multiple models for search, add a single Search model that knows about the things that can be searched on. If you want to prevent duplicate SQL, reuse the SQL between models (this can be done using constants, or loading SQL from disk).
Controllers are not great candidates for reuse from your own PHP code: they route actions and requests for resources to the things themselves. They are intended to be called via HTTP, using the URI interface you've come up with. Calling them from code is a coupling you want to avoid. That said, reusing controllers from JavaScript (or via cURL) is a great, decoupled way to reuse things in any web framework.

Categories