Im just moving over to cakePHP from Code Igniter and I bet its right in front of me, but i can for the love of god not figure out through the manual nor search the internet, how to access relationship data. For example, say I have two tables BOOKS and AUTHORS. When accessing /books/ and getting a list printed, i can have perhaps ID and Title printed, and author_id. But How do I actually print out the authors first and last name? its in the AUTHORS table?
This, in Code Igniter (using dmz) I simply wrote $book->author->first_name
I just cant seem to find/figure out how its done in cakephp.
(Yes i have the relationship set up in the models)
very grateful for anyone to tell me how, or just point me to where to learn it. Not lazy, been looking, just cant find it.
regards,
Jason
If your relationships are setup correctly, you can
echo $data['Book']['Author']['firstname'];
This should allow you to ouput the stuff.
If the 'Author' data isn't in $books you should make sure your recursion is set properly:
$this->Book->recursive = 1;
Or that you have the 'Author' model contained:
$this->Book->find('all', array('contain' => array('Author'));
Related
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.
I know this question has been asked before, but I don't know if it's been asked specifically about CakePHP 2.0.x. I haven't been able to find any information about whether or not having users be a part of multiple groups is now possible with the ACL component. I never used the ACL component with CakePHP 1.3.x because it confused me. If it's better now, though, I'd like to use it so I don't re-invent the wheel by rolling my own. Any help would be appreciated.
I haven't tested it or used it like this before, but I can imagine one way:
Have a User model and a Group model, and User HATBM Group as Shaz Amjad notes.
At the point you're doing your access control, fetch a list of all Groups that User belongs to (probably using bindModel)..
Then, something like:
$permits = array();
foreach ($thisUsersGroups as $group) {
$permits[] = $this->Acl->check($group, 'myclass', 'update')
}
If $permits contains at least one true, they should be permitted.
There might well be a better or more automagic way of doing it, but I don't see what that shouldn't work in principle.
I’m having a problem getting the data from my database which I created to be completely multilingual, and I hope someone here can help me.
I’ve split up all my tables in 2 parts; the “universal” table (does not contain any text that needs to be translated) and the table which contains all the fields that need to be translated with their translations.
Example tables:
base_material
id
picture
base_material_i18n
base_material_id
localization_id
name
description
review_status
review_notes
localization
id
language_name
Query to get the translations (using English (en) as a fall-back language if there is no translation available):
SELECT o.id
, o.type
, o.code
, o.position
, ifnull(t.name,d.name) name
, ifnull(t.description,d.description) description
FROM base_material o
INNER JOIN base_material_i18n d
ON ( o.id=d.base_material_id)
LEFT OUTER JOIN base_material_i18n t
ON ( d.base_material_id=t.base_material_id AND t.localization_id='nl' )
WHERE d.localization_id='en'
My question is how I can automatically get those translations (with the fall-back language as in this query) attached to my model in Yii when I’m searching for the base_material objects? (This is only 1 example table, but almost all my tables (20+) are built in this way, so if possible I would be needing something flexible)
An example of an existing system using what I would need is Propel: http://propel.posterous.com/propel-gets-i18n-behavior-and-why-it-matters
Any ideas how to go about doing that? I’ve checked the existing Yii extensions regarding multilingual sites (like Multilingual Active Record), but they all use a different database design (general information+fall-back language in the main table, translations in the i18n table), and I’m not sure how to change those extensions to use my kind of DB model.
If someone knows of a way to change that existing extension so it can use my kind of DB scheme, then that would be absolutely brilliant and probably the best way to do this.
Edit: I've added a bounty because I still can't find anything on how to let Propel work with Yii (there does exist an extension for Doctrine, but Doctrine doesn't support this kind of DB model with translations either), nor any more information as to how to deal with this using an existing Yii extension or with scopes.
Edit: 98 times viewed but only 3 upvotes and 1 comment. I can't help feeling like I'm doing something wrong here, be it in my question or application/database design; either that or my problem is just very unique (which would surprise me, as I don't think my multilingual database design is that absurd ;-). So, if anyone knows of a better all-round solution for multilingual sites with Yii and/or Propel (apart from the current extensions which I really don't like due to the duplication of text fields) or something similar, please let me know as well.
Thanks in advance!
Have you tried http://www.yiiframework.com/extension/i18n-columns/ (based on http://www.yiiframework.com/extension/stranslateablebehavior/)?
It is an alternate, simpler, approach by adding new table fields in the style of {field}_{language code}, and then setting the translated field in the original model to the current language's translation on afterFind.
In essence, it will get you up and running with translatable fields with the translated content being fetched "automatically", for good and bad :). Adding and removing languages (=columns) is done using migrations.
I am also looking for a generic solution to implement i18n into Yii models.
Recently I chose a very similar database schema for a project like you.
The only difference is, that I am not using a separate language table, I store the language information in the i18n table.
The following solution is without a custom SQL statement, but I think this could be implemented with relation params, anyway, if you're working with foreign key in your database (eg. MySQL InnoDB) gii will create relations between your base_material and base_material_i18n table, like
class BaseMaterial extends CActiveRecord
public function relations()
{
return array(
'baseMaterialI18ns' => array(self::HAS_MANY, 'base_material_i18n', 'id'),
);
}
class BaseMaterialI18n extends CActiveRecord
public function relations()
{
return array(
'baseMaterial' => array(self::BELONGS_TO, 'base_material', 'id'),
);
}
Now you'd be able to access your translations by using the object notation for relations.
$model = BaseMaterial::model()->with('baseMaterialI18ns')->findByPk(1);
foreach($model->baseMaterialI18ns AS $translation) {
if ($translation->language != "the language I need") continue:
// do something with translation data ...
}
I thought about creating a behavior or base class for those models which would act a as helper for managing the translations - pseudo code:
I18nActiveRecord extends CActiveRecord
protected $_attributesI18n;
// populate _attributesI18n on query ...
public function __get($name) {
if(isset($this->_attributesI18n['language_I_need'][$name]))
return $this->_attributesI18n[$name];
else if(isset($this->_attributesI18n['fallback_language'][$name]))
return $this->_attributesI18n[$name];
else
parent::__get();
}
CActiveRecord __get() source
There is more work to be done to find the needed i18n record, also you could further limit the with() option to improve performance and reduce parsing on the PHP side.
But there may be different use cases how to determine the value, e.g. all translations, translation or fallback, no fallback (empty value).
Scenarios could be helpful here.
PS: I would be up for a github project!
You can try to use a simple multilingual CRUD extension.
it is very simple to use and modificate. you just need to add language field to your table.
just watch description here: http://all-of.me/yii-multilingual-crud/
it is in alpha state, but tried on a few projects. you can easily modificate it or contact author to fix or add features
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.
I read a lot about tagging in CakePHP but I can't find a "clean" way to save a Post and the Tags to this post. I have all which is necessary the Post Table, Model and Controller, the Tag table, Model and Controller and the posts_tags table. I created the HABTM Associations in the Post and the Tag Model.
If I want to save a new post, I want that CakePHP automagically saves the tags associated to that post, but I can't find the right way for that. In most of the tutorials you have to use a "helper" Function (http://www.jamesfairhurst.co.uk/posts/view/full_cakephp_application_part_5 => "_parse_genres") or something like that, but I thought the deal with CakePHP is it, that this is all done by Cake once you set it up right.
So my question, is there a "clean"-Cake-way to do it, or do I have to use a helper function?
I find it very hard to believe that you didn't find a "proper" way to handle HABTM. There are many, many articles about it. I believe that Cake will save your tags if you set your data array properly. A quick search on The Bakery:
http://bakery.cakephp.org/articles/search/3/HABTM
Will reveal enough. My guess is that you're looking for this:
http://bakery.cakephp.org/articles/view/simple-tagging-behavior
(Note that there is a component which does the same thing, but model behaviour is the right way to go)