Cakephp: How to re-use code in different controller - cakephp

I have some controller, It use same code idea, only different when call model
ex:
In bookscontroller:
public function abc(){ $this->Book->find(....); }
In categoriescontroller:
public function abc(){ $this->Category->find(....); }
I think it too waste. So, please teach me how to write only one function, but it can call in any controller and load same model.
Thank a lot :)

If you think you need to DRY (dont repeat yourself) that, use components.
They can share code between controllers.
In your case you might also want to look into the crud plugin which takes basic CRUD one step further.

I think it too waste. So, please teach me how to write only one
function, but it can call in any controller and load same model.
You answered half of your question already: DON'T put the code in a controller. Everything related to data manipulating and fetching should go into a model, not a controller.
Assuming you are in your books controller and book belongs to category you can simply call from there:
$this->set('someCategoryData', $this->Book->Category->yourCustomMethod());
$this->set('categories', $this->Book->Category->find('list'));
Need a book from the categories controller?
$this->set('book', $this->Category->Book->view($bookId));
You should fetch the data through the associations and have model methods for your data retrival and manipulation tasks.
A component that calls 1000 models with the logic inside the component is clearly the wrong approach. Read about SoC.

Related

Cakephp Standard - Is it the Proper standard to write things in controller

Sorry for this basic question. The following are the codes presented in my Userscontroller.php
public function register()
{
//Setting some data
$this->User->create();
$this->User->save($this->request->data)
}
public function edit()
{
//Setting some data
$this->User->save($this->request->data)
}
public function admin_add()
{
//Setting some data
$this->User->create();
$this->User->save($this->request->data)
}
public function admin_edit()
{
//Setting some data
$this->User->save($this->request->data)
}
One of my senior reviewed this code and said that the above code not met the CAKEPHP Standard..Business logic need to move to model
like as follows in model
<?php
class User extends AppModel {
//Validation parts
public functions savingData($data =array(), $id=false)
{
if($id == false)
{
$this->create();
}
$this->User->save($data)
}
}?>
And in controllers he is asking to call this savingData function for Create and update options
in MVC, business rules goes to model.
but in your example there is no any business logic so your code is correct to be in controller.
I suggest to use cakephp console to create controller and model and you can get it by yourself.
Usually any method which has validations or save data to other tables or any extra functionality that makes the actions bigger than one page you need to consider it (break the function to smaller functions) and you can put this function base on your need and access into a Model or Component. I can say fat model concept and Component is used for this kind of situation.
I believe that methods shouldn't be more than one page this make the application maintainable for the next developer.
Also any static methods can be inside Utility as a class which can be called from controllers or views ... easily.
Bear in mind that Cake has lots of model behaviours which contained in all models. like beforeSave(), afterSave(), initiate(), before and after delete() ,...
At the end it is entirely up to you how you implement OOP, tidy and maintainable application.
Other example imagine a Car.
All the engine and complected stuff is inside box where you can't see it you can call it Model .
Controller stuff is in front of your hand so you can Controller it. Controller
Hope it helps if any one can add more option to this answer for others to learn.
Generally speaking your boss is correct in that the goal is fat models - skinny controllers. The reason for this is that if at your work they are doing Unit testing ( which I hope they are ) this makes things MUCH easier on you. Testing in the controller is a pain in the rear.
With that being said though the code in your controller is negligible so don't know if what he is asking is "neccessary" exactly, just technically not consistent with current standards ( which will change with time anyway ). Bottom line if you are bothered that he/she made this criticism, try not to be. Things like this are not written in stone and are left up to interpretation for the most part.

Cakephp how should you manage controllers and views

I am completely new to CakePHP, therefore I am fairly confused on how the management of different controls/views/elements works.
The Problem:
I am attempting to create my home page, which has PageController and view home.ctp. Now, I have another controller, IdeaController, which contains function to load all the ideas from the DB.
public function index() {
$this->set('title_for_layout', 'Ideas');
$this->set('ideas', $this->Idea->find('all'));
}
Now, I need to access this Idea Controller from multiple(up to 3) different views. What is the best way to go about doing so?
Thank-you
You're going the other way around...
Views don't "have access" to the controller. The controller receives a request, tells the models what info it need from them, and passes all necessary data to the views. Views are like little dolls you can put clothes on, but nothing more, they don't speak or play or ask random questions to you.
Generally speaking, there's just one view per action in a controller. If you need to "access" the controller from different views, you may be a little confused with cake.
Without knowing the exact reason you need to do this, I'm going to assume you want to "access" the controller from 3 different views only to get all ideas from the BD. If that's the case, the standard way is:
1) Create a function in the appropriate model:
//Idea Model
public function getAll() {
return $this->Idea->find('all');
}
Well, you don't actually need to do that function, since it's so simple, but for more complex cases where you want to get only the ideas of the logged in user and in a certain order, encapsulating that in the model is a mentally-sane way to go.
2) In every action in the controller that the view will need that data, you do
public function randomAction() {
$this->set('ideas', $this->Idea->getAll());
}
3) In every view you receive the data as
pr($ideas);
And that's it.
The views never "access" the controller, so your question turns out to be a bit confusing. Maybe you meant having 3 views associated to the same action, but there's little reason to do that also... Or maybe you meant to have a "view" in a lot of other "views", like the "info" bar on stackoverflow, that repeats everywhere so you need to have it in a lot of views. If that was the case, then you have to do that in an element to reutilize that "view"-code inside other views.
If you clarify a little more what you want, I can probably answer a lot better, but I hope at least I gave you some direction on where to look or how to go about what you want to do.
Each View has to have it's own method in the Controller.
Say, if you want an ideas/index, ideas/view/x and ideas/add pages, you need to create the following methods:
class IdeasController extends AppController
{
public function index()
{
/* index stuff */
}
public function view($id)
{
/* view stuff */
}
public function add()
{
/* add stuff */
}
}
For the sake of understanding the framework, is advisible to do the blog tutorial, as you after that will be very familiar with the core concepts: http://book.cakephp.org/2.0/en/getting-started.html#blog-tutorial
Good luck!

where to add queries ? in a model or a controller in Cakephp

i am working on a Cakephp 2.x.. i have watched many tutorials and read documentation too ... but i didnt get one thing .. i have seen that in some tutorials they write queries in a model and some of them write every thing in controller and model remains clean except they add validation rules etc ... how i am coding right now is like that
class ContactsController extends AppController{
public function index(){
$this->layout='default';
$id = $this->Auth->user('idUser');
$data= $this->Contact->find('all',array(
'conditions' => array('Contact.User_id' => $id)));
$this->set('contacts',$data);
}
}
I wrote the find function here in controller..i have seen in some tutorials they have written this in model class and then call it in Controller .. so i want to ask what would be the best way or what is actually the standard way ? should i have to code everything in controller and write just validation rules in model ? how should i code so that my code looks clean and easily manageable
There are several reasons why you want to do queries in a model:
Data manipulation and fetching is a clear model task in the MVC pattern
You can not re-use queries if done in a controller, simple example is that you want to do something from a shell AND a controller.
Models are a lot easier to unit test than controllers
If you need to change a query you do it in ONE model, not 10 controllers that might do the same query or method.
For an example check the view() method of the controller and model here
Controller https://github.com/CakeDC/users/blob/master/Controller/UsersController.php#L218
Model: https://github.com/CakeDC/users/blob/master/Model/User.php#L536
Same for other methods. Just check how much code is in the model and how much in the controller and try to get an understanding why.
What others stated here is wrong: It is clearly no standard to do queries in the controller.
I disagree with Arkheart. I think you should put it in the model. Your model then becomes essentially a data API for your controllers. You have much cleaner separation of concerns. And to what downside? Your models will have more methods in them. So what.

Data logic on load using a component - cakePHP

I have a project I'm developing which includes articles that can be commented on (comments stored in separate table of course). I want to perform pre logic on a field from each comment, wherever they are loaded through-out the app. The data logic I want to performed is from a custom written component.
The logical place to me that this could be achieved globally is from the comment model, but I could be wrong.
I'm not even 100% if I can use a component from a model, but I've been trying to do this logic using the afterFind() call-back function:
function afterFind($results) {
foreach ($results as $key => $val) {
if (isset($val['Comment']['created'])) {
$results[$key]['Comment']['created'] = $this->Dateconvert->howLongAgo($val['Comment']['created']);;
}
}
return $results;
}
I have tried echoing from inside this function and it doesn't actually seem to be getting called but searching hasn't revealed any functions that do, but I believe afterFind() is best to illustrate what I'm trying to achieve.
So I am looking for a solution where I can performed the post-load logic on articles comments, whether they are being loaded from other controllers with associations to comments or in the comments controller. Basically a global one hit solution :D
cakephp indicates that components are for controllers and behaviours for models and helpers for view...
knowing that first, you may also know that you can use any part of it wherever you want because cake still php, though is not recomended... if is a library of functions you may want to put it inside the libs folders and access it from there.
how, easy use App::import('component', 'nameComponent'); component can be lib, controller, etc..
Having said that, afterFind is a good place to do after load things, remember that this function is call ONLY when a find is used, if you use, any other like query or save or update it won't be called.
hope this helps you :)

in view call to controller function in cake php

i need some help
which is when i on my index.ctp/view.ctp, i need to call to my controller function to perform some task. what code i can use to perform this action?
i need to call to my controller function, which send in a value (user_id) to the function and get me a certain action. how can i do that? i might calling in a javascript function as well.
If you need to call a Controller function from the View, you're doing it wrong. It's not proper MVC.
Having said that, requestAction would be the proper, albeit slowest way to do so. You could hack around a bit more and get an instance of the Controller from the ClassRegistry. But I'd seriously recommend you to restructure your program flow so you don't need to do this to begin with.
You should probably perform the task in the controller before you get the view. But if you need to do some view work on the data you are displaying you might want to consider making a Helper class.
http://book.cakephp.org/view/101/Creating-Helpers
If your task doesn't generate any output - you might want to consider doing it in the controller before you even get to the view stage.
If your task has some form of output - use requestAction with a view Element
http://bakery.cakephp.org/articles/view/creating-reusable-elements-with-requestaction
That link should be a good starting point. There are also good posts by Mark Story on his blog that detail the actual performance of requestAction and it really isn't that bad if you don't abuse it all over the place.
http://mark-story.com/posts/view/how-using-requestaction-increased-performance-on-my-site
http://mark-story.com/nodes/view/reducing-requestaction-use-in-your-cakephp-sites-with-fat-models
If you really need to trigger some sort of logic in a predictable way and that logic might happen in more than one place you can also use an event observer pattern to trigger the controller action you need to run.
http://cakealot.com/2009/04/eventful-a-cakephp-event-system/

Resources