Should I extend Controller or Create Helper? - php

I need to access some functions in multiple controllers in a CodeIgniter application. At the moments the functions are really basic and a few, For example:
generate_random_key() //just a random string
is_logged() //check if user is logged or not
logged_user_only() //if unlogged, redirect
unlogged_user_only() //if logged, redirect
As these functions are related to login, I can either put them in a helper file and place in Application/helpers/login_helper.php
OR
i can extend the CI_Controller, by creating MY_Controller.php and put it in Application/Core/MY_Controller.php
Both of the methods work, but I am wondering which one fits better for this kind of task. I think there should be some rules, when the Controller should be extended or when the helper should be used?

If you're using these functions in your other controllers (and only in your other controllers) I would suggest refactoring them into MY_Controller.
This would also give you direct access to the $CI instance (instead of calling get_instance())
On the other hand, you could create an Authentication library. This might be more suitable..
EDIT::
I would recommend having a MY_Controller as a base, that contains auth wrapper functions, which invoke functionality from a Library that manages this type of thing.

IMO, login functionality has nothing to do with a Controller. That's the reason I would probably put the functions you mention into a helper or a library.

The solution I m thinking:
If you want to follow design pattern, use hook(works like a filter from Java perspective).
Alternate should be extending your My_Controller

Related

Where to put big, rarely used functions in codeigniter

I have a several functions which are quite large, and are only used in one controller function each, and I'm wondering where to put these? They are not displaying any views, but instead crunching some numbers.
If I'm not wrong, there are 4 possible places where i could put these function: in my controller, in a helper, in a library or in a model. But none of these seem appropriate, since I don't want the code to be loaded every time a user uses the controller, and model should be used to do database stuff, and helpers and libraries should contain code that can be used over and over again.
If it is business logic, the best place to put it is in the controller as a private method, then you can call that method from within the controller.
Just as a note, helpers aren't always loaded unless you autoload them or load them in the constructor of your controller. So, as an alternative, you can make these methods of a helper then just load the helper in the controller action you wish to use them. That way they only get loaded when you need them.
CodeIgniter comes with helpers that you probably might not use (doesn't load unless you specify it in the application/config/config.php file) and I don't think its a problem having functions that you only use once stored there (application/helpers ). For example I might use a random password generator once only, but its still there and won't be loaded unless I call it.
$this->load->helper('my_string_generators');

use cakephp component inside a model

How do I use a component that I created in cakePHP inside one of my model classes? Is this possible?
If so, please let me know how I can do so
It is possible but pretty bad practice in a MVC framework. You should re-think and re-organize your code if you think you need to use the component in a model because something is cleary wrong then.
A component is thought to share code between controllers, only between controllers.
Components in CakePHP 1.3
Components in CakePHP 2.x
Components in CakePHP 3.x
To share re-usable code between models it would be a behavior. For a view it would be a helper.
If you have some really generic code it should be a lib or put it in the Utility folder / namespace or create a new namespace. Check the existing classes there to get an idea what to put in there.
No code was provided so it is not possible to give any real recommendation on how to refactor it. However the way you want to use the existing code won't work in the MVC context, so time to rethink your approach of whatever you try to do.
It is possible to use a component inside a model (but I cannot comment if this is a recommended or a best-practice).
Inspired from original source, an example to use a component called ‘Geocoder’ in a model:
App::import('Component','GeoCoder');
$gc = new GeoCoderComponent(new ComponentCollection);
Then you can use $gc to call the functions of the component.
--
P.S.: I do not want to encourage bad programming practices, but sometimes the pressure of deadlines (in real world projects) may force a developer to make such decisions.
#AD7six
// Use anywhere
AuthComponent::user('id')
// From inside a controller
$this->Auth->user('id');
From the cake PHP documentation they provide AuthComponent::user('id') so that it can be used in places other than a controller.
Maybe I need a bigger hint, but why shouldn't my model be able to access ACL information ?

Codeigniter bootstrap like Zend

Is there any way to create a function that works for all controllers in Codeigniter at init?
In Zend there is a application/Bootstrap.php, i need some solution like that.
You could extend the native CI_Controller class and create a MY_Controller class that all of your application's controllers would extend. Methods in the MY_Controller class would then be available to every controller that extends it. You could also put code in the MY_Controller constructor that would be executed each time a child controller was constructed.
I don't remember exactly how the Bootstrap file works in Zend, but if this sounds like a viable solution the Creating Core System Classes section of the documentation explains how to extend the native controller.
You can extend your New_controller to CI_Controller. In New_controller you can write common function which you want. For use about new extended controller you can see this link:
The subject of extending core controllers is discussed briefly in a few places in the manual - specifically in the Core Classes and Creating Libraries pages.
The intent of extending the core Controller is to provide methods and attributes to all your normal Controllers. There are other ways of providing this kind of pervasive functionality - including Hooks, Libraries and Helpers. You should familiarise yourself with the methods and benefits of those alternatives before assuming the following is the answer to your question.
Finally, it’s assumed that you have an application that does something - it doesn’t matter what, merely that you have an existing Controller that we can work with here.
-extend_the_CI_Controller

Having the option of customized classes but a unified class name

Suppose you are building a web application that is going to be a packaged product one day, one that users will want to be able to extend and customize.
It comes with a core library consisting of PHP files containing classes:
/library/
/library/frontend.class.php
/library/filesystem.class.php
/library/backend.class.php
Now, suppose you want to keep a clean core that users can't patch. Still, you want the user to be able to customize every nut and bolt if need be.
My current idea is to create an autoloading mechanism that, when a class is instantiated, first loads the core include:
/library/frontend.class.php
then, it switches to the user directory and looks whether there is an include of the same name:
/user/library/frontend.class.php
if one exists, it includes that as well.
Obviously, the user include must contain a class definition that extends the definition in the core include.
Now my question is, how would I instantiate such a class? After all, I can always be sure there is a definition of:
class frontend_core
but I can not be sure there is a
class frontend_user extends frontend_core
However, I would like to be able to rely on, and instantiate, one class name, regardless of whether there was a custom extension to the class or not.
Is there a clever way, idea, or pattern how to achieve this?
Of course, I could write a simple factory helper function that looks for the user class first and then for the core class and returns an initialized object, but I would really like to keep this as clean and simple as possible, because as I said, it is going to be a packaged product.
I am looking for a smart trick or pattern that uses as little code, and introduces as little new functionality, as possible.
Why don't you follow the approach as used by Propel? You generate your base classes and already provide an empty User class (extending the base class) where your users can put their overrides/specific implementation details, and in your code you always refer to the User classes. So basically you just use the inverse of the logic you described.
If the explanation above isn't clear, check out http://propel.phpdb.org/trac/wiki/Users/Documentation/1.4/QuickStart#a6.UsingtheGeneratedSQLandOMFiles and generate code for a small database. The base classes are in the om folder, the (by default empty) user classes are in the root folder.
I would implement hooks in the core, so users dont have to hack the core, but are still able to extend the core using hooks
I'd go with using the constructor of the core class to determine the user class to load, and then implement a factory method in the core class to generate instances of the user class. By making the constructor of the user class protected, and having the user class extend the core class you can be sure that code elsewhere cannot instantiate the user class.
C.
I think it's more complicated with a single filename when you want to use inheritance as well. Basically class user_frontend extends core_frontend has to know where to find both classes. Both must be included.
If you just want to do new Frontend you could use PHP5.3's class_alias to point Frontend to the main class to use. Below 5.3. you could use a ServiceFinder, that knows how to map Service Names to Classes and then get the Frontend with $service->get('frontend') or use a Dependency Injection framework.
Edit I removed the Loader code given before, because it was suffering from exactly this problem.
You could have a loader class that will decide which class to instance:
Loader::instance()->load('Frontend')

In an MVC Context, Where Do I Put A Class?

straight to the point :
I am using Kohana, and I am looking at another script written in plain PHP. In the script, I have a class ShoppingCart. If I am to convert the script to Kohana, where am I to put the class, its methods and its properties?
Is it in my existing default controller? Or should I put it in a separate controller? Or as noobie as it may sound, will I put it in the model?
That depends on the specifics of the class I suppose. To be honest I don't know anything about Kohana, but there's probably a place for "vendor files" somewhere. Maybe it's best to place it there and write wrapper functions for it in your controller. If the class already integrates well with Kohana you may instead choose to use it as a controller or model directly. Or you might want to take the time to rewrite it to make it work as a controller...
Only you can evaluate the best place for it, there's no hard and fast rule here.
Kohana has a folder for 3rd party libraries. The main one is under system/vendor, you can put it in you application/ as well.
Many PHP class loaders require details like your filename should be the same as the class name (at least that's what I read in the Kohana documentation) if you want the classes to be automatically loaded.
If you need to use 3rd party code in your app it's recommended that you create a folder in your app / module folder called 'vendor' and place all of that code there.
You can then include the files by calling:
include kohana::find_file('vendor', 'filename');
If needs be you can also create a wrapper for the external library, a good example of this is the email helper which uses the 3rd party Swift email library.
If you're porting your own class to kohana then you need to work out what the class will be doing and categorise it accordingly.
If the class will be fetching items from some kind of database then you should make it a model. Libraries are usually sets of code that you want reuse across controllers / models, such as authentication, calendar generation etc. Controllers are used for passing data from models to your views / libraries.
See the docs for more info
As per kohana convention, you should place custom classes in application/libraries folder. However for this, you need to know how to get the class to work after putting it there. If you can't figure that out, you can do anything like putting it in your controller or making another controller of it, etc.

Categories