CakePHP 1.3, Form Helper and Self Joined Table - cakephp

My Self Joined Categories table is as follows:
id, name, description, parent_id
I used Cake Bake to generate the Model, Controller and Views. Model
has the $belongsTo and $hasMany association set up. In add() of the
controller,
$parentCategories = $this->Category->ParentCategory->find('list');
$this->set(compact('parentCategories'));
is present. In the add view, the cake bake generated form is:
<?php
echo $this->Form->input('name');
echo $this->Form->input('description');
echo $this->Form->input('isincome');
echo $this->Form->input('parent_id');
?>
When I run in browser, the parent_id field is getting a drop down, but
it is not being filled with any data. I used
<?debug($parentCategories);?>
in the add view, and it happily outputs
Array
(
[1] => Entertainment
[2] => Groceries
)
But this array is not being used for filling that drop down by the
Form helper. What should I do? Is this a bug with Cake's Form helper in 1.3? It never occurred in 1.2...

When adding an input for field_id, the form helper looks for a variable called $fields. I.e., the name without _id and pluralized. $parentCategories does not fit that description, so it's not used. $parents would be.
Second, $this->Category->ParentCategory is the same as $this->Category. Both reference the Category model. No need to go through ParentCategory.
Third, it's not usually a good idea to join a Tree model to itself. You'll understand why when you start to query with higher recursive settings. You should instead make it a proper Tree and use the TreeBehavior methods to query it.

Related

In CakePHP how can you manually set the ORM table and entity or model backing the Form Helper?

I have a database table called 'items'. CakePhP 3.0 nicely sets up my 'ItemsController' for me. But what if I have another, arbitrarily named, class that wants to access my 'items' table. Call it my 'FooBarController'. In my method in class FooBarController I've added the:
$this->loadModel('Items');
$this->Items is correctly setup, but the $this->Form does not seem to be backed by the 'items' table. I.e. loadModel('Items') correctly sets up $this->Items but does not setup the $this->Form to be backed by Items. How can I manually set up $this->Form to be backed by Items?
Upon creating a form
As shown in the docs, the form expects a model object as the first parameter:
Starting a Form
Cake\View\Helper\FormHelper::create(mixed $model = null, array $options =[])
So, to create a form using Item fields, pass an instance of an item. Put the following line into your .ctp file instead of the HTML statement
echo $this->Form->create($anItem);
If you don't yet have one, create one.

Find record of one type with more than one associated HABTM type

I have two models in my CakePHP application: NewsArticle and Image. Image is associated with NewsArticle using a HABTM (has and belongs to many) association, so authors can build up a gallery for an article if they wish.
On my application’s homepage I want to display the top story, which will simply be the latest published article with at least one associated image. How would I form this condition in my controller? So far, I have:
<?php
$topStory = $this->NewsArticle->find('first', array(
'order' => array(
'NewsArticle.created' => 'desc'
)
));
But I am unsure how to “count” the number of Image records attached to my NewsArticle model.
If you must use HABTM, you'll need to do a JOIN (see CakePHP Joins).
The reason is, normal find()s actually do separate queries, then CakePHP puts the data together before it returns it to you. If you're trying to limit the main results by the existence of sub-results, you'll need to use a JOIN.
If you're able to get away with HasMany instead (meaning an Image would belongTo a NewsArticle), you can use CakePHP's counterCache.
It's often wise to create a CakePHP model for the HABTM join table, then you can query that table.
NewsArticle would have a table named news_articles. Image would have a table named images. So the join table is likely news_articles_images.
I recommend you create model with an alias name that is different from the join table. To prevent problems. So you could do something like this.
class Gallery extends AppModel
{
var $name = 'Gallery';
var $useTable = 'news_articles_images';
var $belongsTo = array('NewsArticle','Image');
}
Then in your controller you can easily find the first article that has an image.
$topStory = $this->Gallery->find('first',array('order'=>array('NewsArticle.created'=>'DESC'));

How to Build one form with input of many views

I have 3 tables/models:
Customer
Address
City
Each one have their views,but I need to add Address and City to the Customer view and there will be all the inputs from each view and it will result in only one Form. I read some stuff about include these views in Customer's view using elements.
What is the best way for doing that?
If I'm reading you right, you have 3 tables, customer, address & city, and want to read them all when you have a user view?
Sounds like you want to set up A CakePHP association, likely a hasOne relationship.
Edit: Here's how you'd use an element to accomplish this:
// Form
<?php echo $this->element('cityselect'); ?>
// app/View/Elements/cityselect.ctp
<?php $cities = $this->requestAction('/cities/index'); ?>
// Use $cities to populate element form
You'll probably want to write an action for your cities/address controllers that returns key-pairs to easily populate your select field.

cake php auto select foreign keys when editing

I am using Cake PHP with scaffolding. I'm having a problem with the code that it generates and want to see if there is a way around it of if I should end up building custom views.
Lets say that I have two models Tests and Questions. Tests can have many Questions and a Question has only one test. I have setup the hasMany and belongsTo Associations.
Now, the scaffolded view that cake creates for Tests gives me a button at the bottom in the "Related Questions" to create a question. When I click this button, I get the 'Add' form for questions, but the right test is not auto selected.
Is there anyway I can make the button pass the test_id into the Question form and have that auto populate?
I see how you think that might work; but Cake doesn't know you want that behaviour out of the box.
You would need to adjust your Question Add method, or create a new one:
Example code:
// action: tests/view/1 (viewing test 1, and all related questions)
// create a link containing the ID of the current test as a param
<?php echo $this->Html->link('Add Question to Test',
array('controller'=>'questions',
'action' => 'add_question',
$test['Test']['id'])
);
?>
So - assuming you have access to id of the current test, you can pass it as a parameter to your questions controller (there are several ways to do this).
Then:
// view - questions/add_question/1
<h1>Adding A Question to Test 1</h1>
<?php
// create your add question form
$this->Form->input('test_id', array('type'=>'hidden',
'value' => $this->params['pass'][0]));
// create a hidden field with the value of the first passed param (the test id)
then in your controller, the test_id is already set, so when you save the question, it is saved with the appropriate test_id
If you want to apply this to all your CakePHP projects generated using cake bake, you can make a couple of small changes to the CakePHP core to enable this, as seen here:
https://github.com/srs81/cakephp/commit/7d92c8f676c79185fa6a74ab2070f240c555a2a0
Basically these two changes append the referring model/controller ID and name to the "add" action, and this is handled in the "add" action where the correct ID is selected.
This does NOT work for HABTM models, but should work fine for anything else.
You need to add var $uses = array('Question','Test'); to questions_controller.php

dropdown select in cakePHP

I am using CakePHP 1.2. I have a person model that hasMany 'Document'. When I edit a document, the select box for the owning person appears (echo $form->input('person') where person has been defined in the documents_controller like this:
$allPeople = $this->Document->Person->find('list', array('fields' => array('first_name')));
$this->set('people', $allPeople);
When I edit a document's record, I want the person owning the document to be selected and displayed in the box. Right now, the app just makes the list box but doesn't highlight the correct owner (though the DB has the person's id).
Thank you,
Frank Luke
In your edit view, you should add an extra parameter to your $form->select(), called $selected. This way, you can specify which item should be selected from the list.
Example (just an example, you should rewrite it for your own situation):
<?php echo $form->select('Document.person', $allPeople, $this->data['Document']['Person']['id']); ?>
More information:
http://book.cakephp.org/view/728/select
-- Bjorn

Resources