1
votes

I'm trying my best to learn MVC and cakePHP and I had a question about passing arrays to the view. Currently, I have some basic code below.

class AwarenesscampaignsController extends AppController {

public function view($id = null) {
    $this->Awarenesscampaign->id = $id;
    $this->set('data', $this->Awarenesscampaign->read());
}

This is what I "think" is currently happening.

AwarenesscampaignsController is set up. The view paramater requests id and matches it up with the Model, Awarenesscampaign. This matches up with the database and returns an array which is set to the variable "$data", and then the view is loaded.

My first question: is my understanding accurate?

What I would like to do is with this is to be able to pass another array, from a different model. For instance, I would like to query the table Posts (Controller: PostsController/ Model: Post).

For instance, my first attempt was to do the following inside the function:

$this->Post->find('all');

But this yields the error:

Indirect modification of overloaded property AwarenesscampaignsController::$Post has no effect [APP/Controller/AwarenesscampaignsController.php, line 20]

Additionally, I'm not sure how I would send both variables to the view.

To recap:

  1. Was my understanding accurate?
  2. How do I query a variable from another controller/model?
  3. How do I sent this array to the appropriate view for that controller?

Thanks, -M

2

2 Answers

2
votes

1) Your understanding is good enough. What this is doing is basically mapping a row of database table with object. So after setting the Model id $this->Awarenesscampaign->id = $id, now Model is pointing to the row of database table that has id equals to what has been passed to view action.

2) you can query another table by calling the methods of that particular Model. If your model is somehow associated with the current Model that you are in, you can use chaining to call that Model's action. e.g. if your in Posts controller and Post Model is associated with Comment Model t get the data you can chain through.

    $comments = $this->Post->Comment->find();

If however your Model of interest is not associated with current Model, there are couple of ways to perform operations of other Model. A good option is to use Class Registry. Say for example you want to use Customer Model which is not related to your current Model. In your controller you will do

   $customer= ClassRegistry::init("Customer");
   $customers= $customer->find();

3) to set multiple variables for the view you can set them via compact function or using associated row.

   $posts = $this->Post->find();
   $comments = $this->Post->Comment->find();

   $this->set(compact('posts', 'comments'));
   // or
   $this->set('posts' => $posts, 'comments' => $comments);
2
votes

You're on the right lines, and aren't doing it wrong per se. I would say your understanding is pretty good for a beginner.

By default Cake automatically loads a model that it thinks is directly related to the controller. So in AwarenesscampaignController, you can automatically access Awarenesscampaign (the model).

It doesn't know about any other model, though. One way you might solve this is by adding the following property to your controller:

// This has to contain ALL models you intend to use in the controller
public $uses = array('Awarenesscampaign', 'Post');

This goes at the top of the class, before you start declaring the functions. It tells Cake that you want to use other models except the 'default' one, but you have to add that one to the array too, or you'll lose access to it.

You can also use loadModel inside your action, if it's a one-off. It's then accessed the same way as you would access a model normally:

public function view($id = null) {
    $this->loadModel('Post');
    $posts = $this->Post->find('all');
    ...
}

To send this to your view, you can call set again, but you might want to change data to something more readable, and to prevent confusion:

public function view($id = null) {
    ...
    $this->set('campaign', $this->Awarenesscampaign->read());
    $this->set('posts', $this->Post->find('all'));
}

They'll be accessible as $campaign and $post respectively.

One tweak I would make, though, is to not use 'read' unless you intend to edit something. You can use findByColumnName to get the same data. Since you're using just an id, you can call findById:

$campaign = $this->Awarenesscampaign->findById($id);

There's quite a lot of magic going on there. It just means you can search for a particular value in a more short-hand format.

http://book.cakephp.org/2.0/en/models/retrieving-your-data.html

Finally, while you can access other models (as demonstrated), you can't, or generally shouldn't, try and access one controller from another. If you have code that you want to use in more than one controller, but can't go in the model, you can create Components.

http://book.cakephp.org/2.0/en/controllers/components.html#creating-a-component

The manual is fairly comprehensive. While sometimes hard to navigate, it will often have an answer to most of your questions.

http://book.cakephp.org/2.0/en/