I have a model, called "Cliente" and this model have a association with another table called ClienteRelFot. I declared that ClienteRelFot has a useTable = 'rel_fot_ec', but the cake are looking for "rel_fots".
The rel_fot_ec table exists on my database because I use to find another data.
Someone have a idea to solve this problem?
I tried clear cache and delete all files from tmp folders.
Below, we have the error:
Error: Table rel_fots for model RelFot was not found in datasource default.
Your associations are trying to pull data from the model 'RelFot' (per the error), not 'ClientRelFot', so declaring that 'ClienteRelFot' uses the table 'rel_fot_ec' will have no effect.
Try adding:
public $useTable = 'rel_fots';
in your 'RelFot' model.
I had this problem too, even though using public $useTable = ...
My data model: Event hasMany > Submissions hasMany > Authors
Cake was telling me [MissingTableException] Table authors for model Author ..., the problem was not in the Author model, but in the Submission model:
class Submissions extends AppModel {
public $hasMany = array(
'Author' => array(
'className' => 'authors', // author should be singular
'foreignKey' => 'submission_id'
)
);
Related
I have taken over a project for cakePHP, I am new and I find it not easy, Magento should be difficult but I find cakePHP more difficult, but maybe I have not reach the moment I know it ...
I have the next model (for table postcodes):
public $belongsTo = array(
'Postcode' => array(
'className' => 'Postcode',
'foreignKey' => 'postcode_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
Everything works, but with the tool AgentRansack I can't find the model Postcode. And besides the name of the table is postcodes, I can't even find a relation for Postcode and postcodes.
How can such a model setup in a different way than with a class Postcode.php ?
When requesting models for which no concrete model class exists (or cannot be found for whatever reason), dynamic model objects will be generated from the AppModel class.
From the CakePHP Cookbook:
CakePHP will dynamically create a model object for you if it cannot find a corresponding file in /app/Model. This also means that if your model file isn’t named correctly (for instance, if it is named ingredient.php or Ingredients.php rather than Ingredient.php), CakePHP will use an instance of AppModel rather than your model file (which CakePHP assumes is missing). If you’re trying to use a method you’ve defined in your model, or a behavior attached to your model, and you’re getting SQL errors that are the name of the method you’re calling, it’s a sure sign that CakePHP can’t find your model and you need to check the file names, your application cache, or both.
http://book.cakephp.org/2.0/en/models.html#understanding-models
By the sounds of it you need to create a class for your 'postcodes',
Read the following: http://book.cakephp.org/2.0/en/models.html
But it should look something like this:
// app/Model/Postcode.php
App::uses('AppModel', 'Model');
class PostCode extends AppModel {
public $validate = array(
// Validation
);
// Replace 'ModelName' with the name of the class where the code sites you mentioned above
public $hasMany = array(
'ModelName' => array(
'className' => 'ModelName',
'foreignKey' => 'postcode_id'
)
);
}
I have the following Models:
class AppModel extends Model {
public $actsAs = array('Containable');
public $recursive = -1;
}
class City extends AppModel { // for "cities" table
public $belongsTo = 'Country';
}
class Country extends AppModel { // for "countries" table
public $hasMany = 'City';
}
..how do I fetch cities for a country. Something like this I'm trying to find out:
$countries = $this->Country->first(); // fetch a country
$cities = $country->city->find('all'); // get the cities for that country
I've set AppModel in this manner to avoid fetching cities every time I call for a country. Sometimes I don't need all the cities to be retrieved so don't want the default join. But, there are times I do want to fetch cities for a given country. The following is the only way I know how:
$cities = City->find('all', array(
'conditions' => array(
'City.country_id' => $country['Country']['id']
)
))
Is this the most convenient way to access cities once relationships have been established in the model? If so, I don't really understand why bother with $belongsTo and/or $hasMany. Thanks
Associated models first will find the main model, and then will find associated models based on the first query. So it's impossible to limit them based on associated model conditions. So, if you want to limit the main model based on the associated model, you have two options:
Do a Join find
Do a reverse find. It means that you can find City based on conditions, and contain the Country associated to it. For example (assuming that you're on CountriesController):
$this->Country->City->find('all', array(
'conditions' => array(
//your conditions
),
'contain' => array('Country')
));
As you are using CakePHP Model relationship, then it's not require to write Join query.
First thing add the following in Model of Country
class Country extends AppModel { // for "countries" table
public $recursive = 1;
public $hasMany = 'City';
}
Just write the following code,
$countries = $this->Country->find('all');
You can get the cities from $countries in an array format.
Is there a way in CakePHP 1.3 to define a model association without having a model for the associated table? For example:
<?php
class SomeModel extends AppModel
{
var $useTable = 'some_table';
var $belongsTo = array(
'AnotherModel' => array(
// association data here
)
);
}
?>
Where AnotherModel doesn't actually have a model file. I just want to define the table that model would use and the association details. Is this possible?
Quick answer is: It should be fine. Have you tried it? Worse case scenario is it won't work without the file, so just add the model file. It takes all of two seconds:
<?php
class AnotherModel extends AppModel {
var $name = 'AnotherModel';
}
?>
Done!
UPDATE
If you follow cake convention on the naming of tables, you should be able to reference the table using the appropriate name without the model file. For example:
my_models = MyModel
your_models = YourModel
model_tables = TableModel
However, if you have a table that does not follow convention, you must create a model file that defines $useTable to indicate which table it relates to:
some_table = model file: SomeTable where $useTable = 'some_table';
another_model = model file: CustomModel where $userTable = 'anotherModel';
There is no other way around it. CakePHP is not magic. It needs to know what table is being referenced. Unless you are doing joins. Then in the join you can reference the table.
//index.ctp, this forms points to action updateData in profilesController
$this->Form->input('User.lastname');
$this->Form->input('Profile.age');
$this->Form->input('Profile.height');
$this->Form->input('Associate.city');
$this->Form->end('Submit');
//user.php
Class User extends AppModel {
var $hasOne = array('Profile', 'Associate'};
var $primaryKey = 'user_id';
}
//profile.php
Class Profile extends AppModel {
var $belongsTo = array('User');
var $hasOne = 'Associate';
var $primaryKey = 'user_id';
}
//associate.php
Class Associate extends AppModel {
var $belongsTo = array('User');
var $primaryKey = 'user_id';
}
//profiles_controller.php
Class ProfilesController extends AppController{
function updateData(){
//output incoming request for debugging purposes
debug($this->request->data);
//here i fetch the db to get the id of user
$options =
array('conditions' => array('User.username' => $this->Auth->user('username')),
'fields' => array('User.id')
);
//find user id so we can find user in related tables
$id = $this->Profile->User->find('first', $options);
//here I modify request data so cakephp finds the users through primaryKeys
$this->request->data['Profile']['user_id'] = $id['User']['id'];
$this->request->data['Associate']['user_id'] = $id['User']['id'];
$this->request->data['User']['id'] = $id['User']['id'];
if($this->request->is('post'){
//this updates data in table no problem
$this->Profile->save($this->request->data);
//this updates data in table no problem either
$this->Profile->Associate->save($this->request->data);
//this returns false...it breaks here
$this->Profile->User->save($this->request->data);
}
}
}
Table structure:
User
|id|int|auto increment
|firstname|varchar
|lastname|varchar
|date|timestamp
Profile
|id|int|autoincrement
|user_id|int
|age|int
|height|int
Associate
|id|int|autoincrement
|user_id|int
|city|varchar
|country|varchar
Ok I know what some of you might tell me, why do I do this on the profilesController and
not on the UsersController. Well, my idea is to separate some actual important user
data from the profile data so it's my intention to write the code for profile on the ProfilesController...as I was developing I was assuming that the same Model association would have automatically updated the User.lastname field in the User table..but that is the part where my code breaks and I have tried but I can't make it work
The current association in my mind at least is as follows:
User has one Profile
User has one Associate
Profile belongs to User
Associate belongs to Profile and User
Can anyone tell me what am I doing wrong? i am following what I think is a logical approach for my application, cakephp updates Profile and Associate models but User remains unaffected.
Assuming the primaryKey of your users table is 'id', just remove all of the $primaryKey lines, and try again.
The only reason to set the primary key is if it doesn't follow the default that CakePHP has in place. I would GUESS (can't see your tables) that the primaryKey field in your 'users' table isn't 'user_id' - more likely it's just 'id', and in the other tables, it's 'user_id'. If that's the case, there's no need to specify the $primaryKey, since that's the default of CakePHP.
As it turns out after reading the cakephp documentation (and obviously being a n00b) the reason why my code was breaking is because I had a callback beforeSave in my model. I didn't know that in order to save data I had to disable the callback which was unrelated to the part of the code I presented to you. The solution in a case like this is to do as follows:
$this->Profile->User->save($this->request->data, array('callbacks' => false));
I don't know you guys but sometimes I feel the cakephp documentation is a little too simplistic, I discover this by looking at the API.
How can i call, from a Model, a function present in another model? I would like not to repeat code.
We can use Model relation to call the function in another model. Eg.
$this->Model->ModelOne->find();
$this->Model->ModelOne->customFunc();
If there is no relation in the models, The we can use
$this->loadModel('ModelName');
To use in the model.
In this case you can use
$this->ModelName->function();
directly as you've loaded that model.
You should try to have relationships between your models. There are many types of relationships which you can read here...
If you have above said associations, you can access your associated models using:
$this->Model->OtherModel->function();
If your models are not related in any way, you should use:
ClassRegistry::init('OtherModel')->function();
You can check out my question on this where I obtained great answers
User App::import()
App::import('Model','OtherModel');
$attr = new OtherModel();
$attr->Othermodelfunction();
if there's a (direct or indirect) relationship between the model, you can call the function: $this->Model1->Model2->...->Modeln->function();
use bindModel
no, you should use ClassRegistry like so:
//MessagesController - in my send() method...
$this->set('content', ClassRegistry::init('Content')->find('first', array(
'conditions' => array('Content.id' => 3)
)));
NOTE:this is from my controller but I am pretty sure it works in model too.
In 2.x versions the $this->Model1->Model2 syntax answered above will not work. Calling functions from another models in many cases is the job of a controller, not the model. Consider that, the model methods should be limited to querying and updating data whilst maintaining database integrity.
1st method: using the controller
I'll illustrate this with an example of Firm and User models, while Firm hasMany users. This method is recommended, if you plan to add extra controller functionality inbetween, such as setting flash messages or cookies.
User model:
public function saveRegisteredUsers($user_data,$firm_id){ ... }
--
FirmsController:
public function add(){
if($this->Firm->save($this->request->data)){
// set $this->Firm->id here
$this->loadModel('User');
$this->User->saveRegisteredUsers($this->request->data['User'],
$this->Firm->id);
// ...
}
}
2nd method: using the model
For this you will need to have correct model associations. The table names have to be users and firms conventionally. Following the terminology of the example above your relation should be defined as this in the Firm model:
public $hasMany = array( 'User' => array(
'className' => 'User',
));
In the User model, you have to set up the belongsTo association properly:
public $belongsTo = array(
'Firm' => array(
'className' => 'Firm',
'foreignKey' => 'firm_id',
'dependent' => false
)
);
After this, you can call $this->User->saveRegisteredUsers() directly from any of the Firm model methods.
If you have a model function that you want to call from many models, the best approach is to abstract any references to the model name ($this->alias) and place the function in AppModel. Then it is accessible in any of your models.
class AppModel extends Model{
public function myFunction($options = array(){
do some stuff with $this->alias;
}
}