15

I have a controller/model for projects. so this controls the projects model, etc, etc. I have a homepage which is being controlled by the pages_controller. I want to show a list of projects on the homepage. Is it as easy as doing:

function index() {
    $this->set('projects', $this->Project->find('all'));        
}

I'm guessing not as I'm getting:

Undefined property: PagesController::$Project

Can someone steer me in the right direction please,

Jonesy

1

3 Answers 3

57

You must load every model in the controller class by variable $uses, for example:

var $uses = array('Project');

or in action use method

$this->loadModel('Project');
Sign up to request clarification or add additional context in comments.

4 Comments

if seems to have worked thanks! one more question though would I use it in the view like so: foreach($projects as $project){ echo $project['title']; echo '<br />'; } because it's telling me title is undefined
I can't tell you this now because I don't have code to run now, but please var_dump() the content that is being returned by find() and see where exactly is 'title' located in tree.
got it foreach($projects as $project){ echo $project['Project']['title']; echo '<br /><br />'; }
When using the $uses attribute in your controller you need to specify also the current model i.e you are in the UsersController and need the Projects model you should load both models var $uses = array('User','Project');
2

In my opinion the proper way to do this is add a function to your current model which instantiates the other model and returns the needed data.

Here's an example which returns data from the Project model in a model called Example and calls the data in the Example controller:

Using Project Model inside Example Model:

<?php
/* Example Model */
App::uses('Project', 'Model');
class Example extends AppModel {

    public function allProjects() {
        $projectModel = new Project();
        $projects = $projectModel->find('all');
        return $projects;
    }

}

Returning that data in Example Controller

// once inside your correct view function just do:
$projects = $this->Example->allProjects();
$this->set('projects', $projects);

In the Example view

<?php
// Now assuming you're in the .ctp template associated with
// your view function which used: $projects = $this->Example->allProjects();
// you should be able to access the var: $projects
// For example:
print_r($projects['Project']);

Why is this "better" practice than loading both models into your controller? Well, the Project model is inherited by the Example model, so Project data now becomes part of the Example model scope. (What this means on the database side of things is the 2 tables are joined using SQL JOIN clauses).

Or as the manual says:

One of the most powerful features of CakePHP is the ability to link relational mapping provided by the model. In CakePHP, the links between models are handled through associations. Defining relations between different objects in your application should be a natural process. For example: in a recipe database, a recipe may have many reviews, reviews have a single author, and authors may have many recipes. Defining the way these relations work allows you to access your data in an intuitive and powerful way. (source)

Comments

0

For me it's more reasonable to use requestAction. This way the logic is wrapped in the controller.

In example:

//in your controller Projects:

class ProjectsController extends AppController {
  function dashboard(){
    $this->set('projects', $this->Project->find('all'));
  }
  $this->render('dashboard');
}

Bear in mind that you need to create dashboard.ctp in /app/views/projects of course.

In the Page's dashboard view (probably /app/views/pages/dashboard.ctp) add:

echo $this->requestAction(array('controller'=>'projects', 'action'=>'dashboard'));

This way the logic will remain in the project's controller. Of course you can request /projects/index, but the handling of the pagination will be more complicated.

more about requestAction(). but bear in mind that you need to use it carefully. It could slow down your application.

3 Comments

It seems to me that using requestAction "ruins" the MVC structure. The only reason for using it might be in elements.
Agree, but this way you encapsulate the module in separate plugin, so it can be reused.
@OfirBaruch I think it doesn't ruin the MVC structure everywhere. It depends where you use requestAction(). If you use it in View (page or element) it's OK, but elsewhere, yes, it ruins the MVC structure.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.