Cakephp - Load a view from another view in a different controller - cakephp

I've been trying for the past 2 days, how to embed a view from a different controller.
I have two tables (hotels, hotelQuotes), related to each other. The hotels table is linked with a hasmany to the hotelQuotes table, and hotelQuotes with a belongsTo hotels table. Both are linked and working, they both show their related content with no problem.
The hotelQuotes it's pretty much a form, where users fill it out, and then it sends an Email with what the user filled out. Everything is working fine up to this point.
What I want is, when I show the information about the hotel, is to also show that form, I dont want the user to go to another page to fill out the form. So I pretty much want to embed the view of hotelQuotes/Add to the hotel/view.
I doing that using elements, as recommended last night in #cakephp IRC channel, and also here in StackOverFlow at: Embedding view in another view with CakePHP
The problem is that when I do that, the association between the two models gets broken. I mean, the users fill out the form, but I have nowhere to know where that form is coming from, what hotel is referring to. It just doesn't show that piece of vital information for me.
I've been reading about passing variables when using elements at: http://book.cakephp.org/2.0/en/views.html#passing-variables-into-an-element but I don't know how to pass a variable to a form select box. I am using CakePHP 2.5.2.
I hope I explain myself clear here, any input it would be appreciated. See picture below for more info:
http://i.stack.imgur.com/wcG64.jpg
Edit> I just realized that the form is not even submitting when I using elements. Why would that be?

Ok, I just figured out.
The form wasn't even submitting when calling it from elements. So I just passed the action myself like so:
echo $this->Form->create('Hotelquote', array(
'action' => 'add'
));
And now is working.

Related

Get content Id (nid) from path on views block

I just can't seem to wrap my head around Drupal relationships. I have been reading and watching tutorials, but as soon as I try to get my own project done - I fail. I think it's very basic, so I would love to understand it. Maybe someone here can help me understand how it works :)
On my drupal site, I want to keep track of some private game tournaments.
I have created a content type called contestant, which has fields like: Tournament date, Player name, Final Position. I can then create a view that list the information from one tournament. I used the help I got from this thread: drupal views dynamic filter
I would like to have the view described above as a block. And then place that block-view on a "tournament description" page. I could do this, by simply creating a new block each time, and then manually place it on the page it should be shown (structure-->Blocks-->configure), but that is not an elegant way to do it. I am pretty sure this is where Relationships should be used. But I fail to understand how to create this relationship, so that the specific block view, that matches the specific tournament description page will be displayed together.
Use a Content:Nid as a Contextual filter.
WHEN the Filter value is not in the URL >>
Provide default value
Content ID from URL

Is this the right db design for the most flexible and modular CMS with user management in CakePHP?

I would like to ask you guys if you could review my database design. I think it is quite self-explanatory, but to be absolutely clear:
My goal is to make an application which has a super flexible user management (which is why the groups are in tree-form and the groups and users have a habtm relationship) and a super modular way to build pages (which is why the pages consist of widget-blocks).
The reason I made users and profiles separate is because the users table will not change and is only needed for authentication and authorization. However, the profiles table will change according to the wishes of the client. So it might not have a signature, but an avatar field instead. Or maybe it will be completely empty / not exist at all.
A widget could be anything, it could be a poll, it could be a piece of content, it could be a navigation, it could be a collection of comments, whatever.
The reason I chose to make subdomains, locales and layouts separate tables instead of just putting the names into pages is because I want to limit the options that are available to the client. Just because I have a three-columns.ctp in my layouts folder doesn't necessarily mean I want the client to be able to choose it.
Same goes for the widgets. And besides limiting choice, not every plugin, controller and action in my plugins-folder is a widget, so I need a table to clarify which are.
A block is a widget on a page which sits in a container (e.g. the right column in a 3 column layout) at a particular position which is decided by the index (lower index means higher).
So that's my explanation, what do you guys think? Is this as good as it can be? Or do you have (a) suggestion(s) to make it even more flexible and modular.
[edit] Oh and to be clear, the widgets will of course have their own tables to store the information they need to store.
Well, I think that everything is great except "profiles".
When you try to get data from a logged user:
$this->Auth->user();
I don't think that you will get data about "profiles" so you will have to find profile by $this->Auth->user('id') etc. I think that you should merge "profiles" and "users" tables into "users" table.
So when you want to save, let's say, "signature" you should just put it in $this->request->data; and call $this->User->save($this->request->data); and the signature will be updated.
EDIT:
You can leave it the way it is but, to get other data than user, you will have to put:
$id = $this->Auth->user('id');
$current_user = $this->User->findById($id);

CakePHP - Prevent model data being save in a saveMany call when certain fields are blank

I have scenario where I have 3 different models data being saved from one form, by means of the saveAll pass through method in CakePHP 2.x
The models on the form are:
Project
ProjectImage
ProjectAttachment
1 and 2 are saving perfectly, but I am having problems with the ProjectAttachment fields. If you look at the following image, the fields in question are at the bottom right, highlighted by a red frame: http://img.skitch.com/20120417-bnarwihc9mqm1b49cjy2bp13cf.jpg
Here is the situation:
I have named the fields as follows: *ProjectAttachment.0.project_id*, ProjectAttachment.0.name .... *ProjectAttachment.6.project_id* etc where the numbers are relative to the already present amount of attachments the user has added, as there is no limit. So if the user has ALREADY added 6 documents, the field would be called ProjectAttachment.7.id and so on. This is because of the naming convention when using the saveAll method.
I have made use of two hidden fields, one to store the user ID, the other to store the project ID.
The problem is that if the user does not fill in the Document Title and select a file to upload, the form fails! If I remove all validation rules, the form no longer fails BUT a blank ProjectAttachment record is inserted.
I suspect the problem may also be that the project_id and user_id fields (that are hidden) already have values in them?
I gave it some thought, and came up with a simple concept: In my controller, before the saveAll call, I would check to see if a blank Document Title field was submitted, and if so, I would completely eliminate the relevant array entry from the $this->request->data['ProjectAttachment'] array, but this did not seem to work.
To clarify, I am not looking for validation rules. If the user decides they only want to upload images and not touch the ProjectAttachment form, them the saveAll operation must not fail, it must simple not attempt to save the blank fields in the form, if this is at all possible.
Any suggestions?
Kind regards,
Simon
Well it seems that the solution was far simpler than I had initially thought! I was partially on the right track, and I had to unset the variable ProjectArray key in the $this->request->data array if I had encountered any blank fields.
I did this as follows:
if(!empty($this->request->data['ProjectAttachment'])){
foreach($this->request->data['ProjectAttachment'] as $key => $value){
if(is_array($value) && array_key_exists('upload_file', $value)){
if($value['upload_file']['name'] == ''){ // Blank document file
unset($this->request->data['ProjectAttachment']);
}
}
}
}
I hope someone finds this somehow useful in some form or another.
Kind regards,
Simon

Getting related data using Wizard Component

The short version of this question is:
How can I take data that only exists in an array (ie: not saved in a model yet) and relate it to a value in a $this->find('list') array from a model?
The long version of this question is:
I'm using CakePHP and the Wizard Component for a 3-step application form.
The 3 form steps are contact, course and details.
After these steps, there is a 'review' step which I want to display all of the submissions from the previous 3 form steps for the user to check one last time before pressing submit. For the most part, this works very well. I just need to do the following in the controller:
function _prepareReview() {
$contact = $this->Wizard->read('contact');
$course = $this->Wizard->read('course');
$details = $this->Wizard->read('details');
$this->set(compact('contact','course','details'));
}
Then, in review.ctp I can reference things like $contact['Contact']['firstname']; to get the person's firstname etc.
However, the problem is getting data from 'related' models. For example, there's a "Nationality" field which is just an ID. In the 'details' step, I use find('list') to get a list of all nationalities from the Nationality model as a dropdown menu which displays properly and then Cake saves the corresponding ID as it should do.
But, when I come to the 'review' step in the Wizard Component, I only get the actual ID from the Wizard Component's array. I couldn't really expect to get anything else.
I can't see any obvious way to access $details[Detail][Nationality][name] (or something like this) from the context of the Wizard Component because setting recursive doesn't work because the data isn't actually in the model at this stage, it's just an array of form data.
So, in other words, I have data in an array (NOT coming from a model, but from a form subsmission) as follows:
Array
(
[Details] => Array
(
[firstname] => Test
[nationality_id] => 3
)
)
Then I have the following coming from a $this->Detail->Nationality->find('list') which looks like this:
Array
(
[0] => American
[1] => Australian
[2] => British
[3] => Canadian
)
So how can I get $details['Details']['nationality_id']; from the Wizard Component to display 'Canadian' instead of '3' for example? How to I make the relationship when only one of the arrays is coming from a model? I only need this to momentarily confirm all of the data to the user. The id '3' will, of course, be written to the Model once the user presses submit, and this is already working as it should do.
Or is this a completely crazy way of doing things and I should look at a totally different approach such as saving the data first? I don't really want to save it until the user clicks the final submit, though.
I can see what you are getting at here - CakePHP isn't automatically querying these related models for you (as you aren't pulling from the database) but you can't help but think you are missing out on some of the framework's free functionality.
If you were still using FormHelper::input() it would automatically select the correct option (given you perform a Model::find('list') and passed the options list to the view first), but I'm assuming you wish for the review screen to be free of form inputs (disabled or not).
The most straightforward approach would be to simply perform the same Model::find('list') calls you do for each step in the wizard, set the data from each to the view, and print out the appropriate value manually:
// controller
$nationalities = $this->Review->Details->Nationality->find('list');
$this->set(compact(/*..., */ 'nationalities'));
// view
<?php echo $nationalities['Nationality'][$details['Detail']['nationality_id']]; ?>
outputs 'Canadian' (the value for $nationalities['Nationality'][3])
It might be possible to get CakePHP to do it for you by calling DboSource::queryAssociation() just right - if your up for the challenge - but is probably overkill for this particular problem.
// model
$db =& ConnectionManager::getDataSource($this->useDbConfig);
$data = $db->queryAssociation($model, $linkModel, $type, $association, $assocData, $queryData, $external, $resultSet, $recursive, $stack) {

Cakephp habtm saving data

Good evening.
Mabye I am blind, but I can't find a solution to this: I have 2 models, Post and Tag with fields post_text and tag_name, where Post habtm Tag.
Now I have form, where I input post_text and couple of tag_names. And I would like to save each of these Tags, keep them unique (so if the Tag is already in DB, don't save it, just get the ID of it), then save the Post and finaly relate the Post with the Tags via posts_tags table.
Now everybody tells me: leave it on Cake, it can do all this work for you! OK, I would love to, but how should my $this->data array look like?
I am trying Tag.tag_name, Post.Tag.tag_name, Post.Tag.0.tag_name, Post.PostsTag.0.tag_name, Tag.Tag.tag_name, Post.PostsTag.Tag.0.tag_name, ...
I am trying save(), saveAll(), ... nothing works. And all the examples on the web (including Cake Book) are working with Tag IDs, not Tag names.
Is there a way (I mean $this->data array form), that I can post to $this->Post->save() or saveAll() and it will do all the magic for me?
Thank you very much.
Josh.T.
Afraid you'll have to write the saveUnique() method yourself, someone may correct me but I don't think cake's automagic goes that far.
You'll basically have to check for each tag, if it exists, get the id(s) into an array - otherwise make it and get the id(s). Then pretty much save that array as a standard habtm with the original post.
It may even be worth using someform of AutoComplete on the add form to get tags that already exist, and then only have to create the one's that don't exist and then saving them + the habtm relationship.

Resources