Short functions from a Codeigniter's library - php

I got a Tank Auth library installed in my Codeigniter package, the problem is that I don't like how to is_logged_in functions need to be called because it's simply long and not so friendly, as I need to use:
$this->tank_auth->is_logged_in()
Everytime I want to check if user is logged in...
So is there a way to make it shorter? By saying shorter I mean something like $this->logged();?
I would really appreciate if someone could help me.
Thank you.

Head into the tank_auth library and define a new public function:
public function logged(){
return $this->is_logged_in();
}
You can now access it with $this->tank_auth->logged();
If you want to shorten the name of tank_auth, you'll have to rename the class and the filename.
UPDATE:
The more important question is, why are you calling this so many times that it is becoming an annoyance? You should only have to write it once if your code follows the Don't Repeat Yourself (DRY) principle.
Have a look at Phil Sturgeon's blog post entitled Keeping It DRY. He will show you how to write a base controller that all your controllers will inherit from. If you write the login check in the constructor of the base controller, you don't have to write it in every controller.

I would argue against doing this as the method logged() in your instance lacks context. However, if you wanted to do this, you could write a base controller which has a logged() method which ends up returning $this->tank_auth->is_logged_in(). All controllers would inherit from this base controller, which isn't a bad idea to begin with.
If you're using libraries, you could implement a similar pattern in them.

You probably don't want to edit anything in the TankAuth library if you didn't create it as doing so affects the updatability of the library. Instead, you might add a method to your controller called logged and have it reach out to Tank Auth. Although, I would choose a better name for your function as pointed out by a previous answer.
Create or edit your controller base class to have something like this:
function is_logged() {
return $this->tank_auth->is_logged_in();
}
Then you may call it like so: $this->is_logged();

Related

Cakephp custom folder structure for admin

Since my app is getting bigger i would like to separate admin prefix actions and views from normal actions and views. The new folder for admin is Controller/admin/UsersController.php.
I would like to change my cakephp controllers and views folder structure to match the prefix I'm using.
Example for admin prefix:
Controller:
app/Controller/UsersController.php (contain view(), index() ...)
app/Controller/admin/UsersController.php (contain admin_view(), admin_index() ...)
View:
app/View/Users/index.ctp (for index() in UsersController.php)
app/View/Users/admin/index.ctp (for admin_index() in admin/UsersController.php)
How can I implement this structure using Cakephp 2.6?
Unlike in 3.x where this is the default behavior for prefixes, this isn't supported in 2.x.
You could try hacking it in using a custom/extended dispatcher (in order to retrieve the desired controller) or even dispatcher filters in case you are adventurous, and in your app controller modify the view template path with respect to the prefix.
That should do it, however I would probably simply go for using plugins instead, this will separate things just fine without any additional fiddling.
If you just want to separate logic you could do something like this. It's untested an just thought to give you just the idea. I'll explain the concept after the code:
public function beforeFilter() {
if ($this->request->prefix === 'foo') {
$name = Inflector::classify($this->request->prefix);
$className = $name . 'ChildController';
App::uses($className, 'Controller/Foo');
$this->ChildController = new $className($this);
}
}
public function __call($method, $args) {
if ($this->request->prefix === 'foo' && method_exists($this->ChildController, $method)) {
call_user_func_array([$this->ChildController, $method], $args);
}
}
Depending on the prefix you can load other classes. How you load that class and how you instantiate it, what params you pass to it is up to you. In my example I'm passing the controller instance directly. I think you could actually init a complete controller here but be aware that components like the Session might cause a problem because they might have been already initiated by the "parent" controller.
When you now call a controller method that doesn't exist it will try to call the same method with the same arguments on the ChildController. Not really a great name for it, but maybe you can come up with something better.
You'll have to implement some logic to load the views from the right place in your classes as well but this shouldn't be hard, just check the controller class.
But actually I don't see your problem, I've worked on an app that hat over 560 tables and not putting the code into sub folders wasn't a problem, it did in fact use a similar solution.
I think you have to much code in your controllers, get more code into your models and the controller shouldn't be a problem.
Another solution might be to think about implementing a service layer in CakePHP which implements the actual business logic while a model is reduced to a data handler. The service would sit between a controller and the model. I've done this a few times as well now and if done right it works very well.

Laravel: Difference between View::share() and View::composer()

In relation to the question Passing default variables to view, to pass variables available among all views, is there a technical or functional difference between the use of View::composer():
View::composer('*', function($view) {
$thundercats = 'Woooooohh!!';
$view->with('thundercats', $thundercats);
})
in the filters.php file or the use of View::share() in the BaseController.php file:
public function __construct {
$thundercats = 'Woooooohh!!';
View::share('thundercats', $thundercats);
}
I've only recently learned about View::share() and find it exceptionally intruiging although I've already started using the former in another project.
Edit:
My first assumption is that the former is a file (filters.php) while the the latter is a class (BaseController.php). With this in mind, I'm guessing a class is much better? Although, I'm not quite sure why at this point. :)
Technically they are not at all alike. View::share simply sets a variable, while View::composer is a callback function.
Let me explain in greater detail:
View::share is really straight forward it sets a variable which can be used within any of the views, think of it like a global variable.
View::composer registers an event which is called when the view is rendered, don't confuse it with a View::creator which is fired when a view is instantiated.
View::composer / View::creator can both be used as a class which is well documented.
While these give you the ability to pass additional data to a view, they also give you to ability to do a lot of other things, for example they could:
Aid in debugging a view
Log information about views
Be used to create custom caching (probably not a great idea, but possible)
These are just some examples of what could be possible using View::composer and View::creator.
View::composer('*', callback());
Means that the callback will be called for all views (*).
View::share
Means that a variable will be shared with all outputed views.
Because the first is in filters.php, it'll apply for all routes.
The second is in a controller contructor, so it'll apply for all views triggered by this controller.
One last thing: when overriding a constructor, it's a good pratice to allways call the parent constructor with this code:
parent::_construct();

codeigniter shorten method

I am using codeignitor , currently i have a library named "Common_func" which is autloaded.
and i can call it like this everywhere
$this->Common_func->common_method();
its ok in case of working with controllers and models , but in case of views it makes the HTML ugly ,
I know about the template parsing options , but i do not want to go with that.
is there any posible way to access with a shorten structure.
like this (or similer with least words)
Common_func->common_method();
or better than this.
Thanks.
The best practice is not to use libraries in View files at all, libraries are meant to be used in controllers and models. Helpers are used for views, they are random functions that help you with formatting/code generation and sometimes even more.
Nevertheless, if you really want to keep your library and it's methods you can make "abstract" helpers, that will help you with making view files clean and readable:
common_helper.php
function common_method($arg) {
$ci =& get_instance();
return $ci->Common_func->common_method($arg);
}
That will keep your helpers updated with the changes made in the library.
I found this in codeigniter forum. This link might help you
http://codeigniter.com/forums/viewthread/139788/
or you can shrink a little if your library name is pretty long this way
class SomeClass extends CI_Controller{
function __construct(){
parent::__construct();
$this->lib=$this->Really_Long_Library_name;
}
}
this way you can use $this->lib to access its methods.

shifting controller function to library in codeigniter

I am trying to put this function ((click_add)) in library so that i can call it from all the controllers. I already have get_ads() function in library. I tried various ways to shift the click_add(id) function to library and call it to view along with get_ads but doesn't work. Please help
function __construct() {
parent::__construct();
$this->load->library('ads');
$this->load->model('MGlobal');
}
public function index(){
$data['banner']= $this->ads->get_ads();
$this->load->view('test',$data);
}
//i want this in library but no luck
public function click_add($ads_id){
$ads_site = $this->MGlobal->getAds($ads_id);
$this->MGlobal->add_ads_view();
redirect($ads_site['url']);
}
//and views is like this
foreach($banner as $k=>$list){
echo anchor('test/click_add/'.$list['bannerid'],'<img src="'. $list['image']. '"/>');
}
please suggest me how do i achieve that with library
It's also important to remember the role of each part of the MVC pattern. In your click_add() method, it looks like you're rendering a view and causing a redirect. These are two things best suited for a controller rather than a library. Rendering views and redirecting are two things that must be a controller's responsibility, and indeed, you won't be able to access them through the URL, which is what you're trying to do here.
If you want to reuse this method across multiple controllers in your site, try creating a MY_Controller core class and extending your controllers from that. That way, any methods you define in the MY_Controller will be available in any controller you subclass from.
Without any specific error messages or a more verbose description of the problem you're having, I'm afraid there's little more help I can give you.

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.

Categories