The situations looks like this: I have two models with controllers and everything, WrittenTest and WrittenTestAnswer. The problem is that whenever I try to access model WrittenTestAnswer, both from WrittenTestsController (using $this->loadModel() before) and from its own WrittenTestAnswersController, it somehow accesses WrittenTest instead. I noticed it when data wasn't saved to WrittenTestAnswer, $this->WrittenTestAnswer->find() also returned data from written_tests table. I have no idea what's going on. I checked names and stuff so many times already. I am using CakePHP 1.3. Thanks for any help.
EDIT:
code from WrittenTestAnswer model:
class WrittenTestAnswer extends AppModel {
public $name = 'WrittenTestAnswer';
public $displayField = 'written_test_answer';
public $belongsTo = array(
'WrittenTest' => array(
'className' => 'WrittenTest',
'foreignKey' => 'written_test_id',
),
);
}
EDIT so for example this (in WrittenTestAnswersController)
debug($this->WrittenTestAnswer->name);
outputs WrittenTest. And
$this->WrittenTestAnswer->find('first');
returns first row from written_tests. Any idea what's going on?
How are you accessing the model? If the relationships are setup correctly, you shouldn't need to use $this->loadModel() at all. You can just access the related model through its parent like so:
$this->WrittenTest->WrittenTestAnswer->find('all');
This might not be the cause of your problems but we cannot tell until you actually post the code that's not working.
Related
So i have a task of creating a mobile version of an existing website but its built with a different framework which i didnt started.
The client wants to use CakePhp on it. so im using CakePhp 2.5.7. My question is. Is there a way to relate another table from an existing table without using prefixes?
To make it more clear i have this on my controller
public function index(){
$this->loadModel('Bulletin');
$bulletins = $this->Bulletin->find('all');
}
in my model
class Bulletin extends AppModel{
var $useTable = 'bulletin';
var $hasMany = array(
'BulletinComment' => array(
'className' => 'BulletinComment',
'foreignKey' => 'bulletinid',
),
);
}
but the bulletincomment table on the database has no prefix. and showing error on page
Error: Table bulletincomments for model bulletincomment was not found in datasource default.
I tried creating BulletinComment model like this
class BulletinComment extends AppModel{
var $useTable = 'bulletincomment';
}
but to no avail. Im still getting error. Is it possible to use any relation without adding prefixes?
Assuming prefixes are setup in the database connection (/app/Config/database.php) you can override it for one table if you add this to the model:
public $tablePrefix = '';
Or you could remove the prefix in the connection and add it back for the models that need it, depending on which is faster.
I'm working on the Admin view in Yii for my Project model.
One of the columns with a filter is user (owner) of the project.
I can do something like this:
'filter'=> CHtml::dropDownList('Project[user_id]', $model->user_id,
CHtml::listData(User::model()->orderAsc()->findAll(),
'id','username'),array('empty'=>'(select)')),
Which gives me a list of all users in the user table, but I'd like to create something that pulls the distinct users who own a project (I've got 200 users, but only a handful tend to create projects).
Project and User are related via:
'user' => array(self::BELONGS_TO, 'User', 'user_id')
I've tried a bunch of option in the findAll() method, but none worked, I'm not trying to do something with a scope.
So far I've tried this:
'filter'=> CHtml::dropDownList('Project[user_id]', $model->user_id,
CHtml::listData(Project::model()->with('user')->ownerUsernames()->
findAll(), 'id','username'),array('empty'=>'(select)')),
and my Scope is defined as:
'ownerUsernames' => array(
'with' => 'user.username',
'select' => 'user.username',
'distinct' => true,
),
I've tried so many iterations of the above I've lost count 'with'=>'username' 'select'=>'username' etc., but just can't seem to get it to work.
I've tried replace Project::model() with $model just because I thought it might have something to do with it, but no luck.
Any ideas are appreciated. Very new to Yii, but this seems like something it can do.
You have everything ready. Define for the project model a getter function like
public function getUsername()
{
return $this->user->name;
}
Now you should be able to use
CHtml::dropDownList('Project[user_id]', $model->user_id,
CHtml::listData(Project::model()->with('user')->ownerUsernames()->
findAll(), 'id','username'),array('empty'=>'(select)'))
The logic is that CHtml::listData will get the projects as a model, it will create the keys using $project->id and it will create the values using $project->username. Because you created the getted function it will know what $project->username is. Unfortunately CHtml::listData(Project::model()->with('user')->ownerUsernames()->findAll(), 'id','user.name') will not work because it cannot execute 'user.name' or anything like that.
actually you can do many things to accomplish that but some methods would be not appropriate due to time consumption. I prefer to tackle this problem as
Make a table in DB named user_project with attributes
id
user_id(fk to user table)
project_id(fk to project table)
When you create a project then also populate user_project with given fields.
Make its model and you will see relations in it. Now make a function like
public function getName()
{
return user->name;//here i have assumed that the relation name is user
}
Now query this table like
$user=UserProject::mode::findAll();
$list=CHtml::listData($user,'user_id','name');
and use this list to populate the dropDownList. The benefit of this method is that you dont need to query all users of the user table.
I have a User model that is used to store data on users of a dental examination system.
Typically, three types of users will exist: Admininistrator, Location Manager and Examiner.
It seems to have become necessary to treat these three roles as seperate models in my application (imagine how I'd have a different view for each role with different options etc... It's a nightmare).
How would I go about setting up the relationships in each Model.
My first thought is:
//Administrator Model
class Administrator extends User {
$name = 'Administrator';
$table = 'User';
$belongsTo = array(
'User' => array(
'className' => 'User',
'conditions' => array('User.role' => 'administrator'),
)
);
}
And then the User model will reference this one using a hasMany? In terms of CakePHP convention, how would one actually model this accurately?
Also, would this model extend the User model or the AppModel?
Of course you can create different models using the same table name. To do so, link each model with specific table with $useTable property (not $table):
class Administrator extends AppModel {
public $useTable = 'User';
}
But I don't know any CakePHP model property which will allow you to filter data returned when fetching results... You can only write your own conditions when linking model with another one, for example:
class SomeOtherModel extends AppModel {
public $hasMany = array(
'Administrator' => array(
'className' => 'Administrator',
'conditions' => array('Administrator.role' => 'administrator')
)
);
}
Which is not a good solution, because it will work only when executing queries for SomeOtherModel model.
You can also try applying an afterFind() callback to your Administrator / Examiner / ... models which will delete users of another role than needed, but of course it is not an efficient solution.
Another solution is just creating different database views which will contain only users of selected role (more on views - here). Then you can point each view to your CakePHP model, just as it was a normal database table.
But this solution is also not perfect. If you will have to add a new user role or change your table schema in the future, you will also have to modify your database views.
So, I have this piece of code:
class ProductsController extends AppController {
var $name = 'Products';
var $paginate = array('limit' => 5); // sets the number of entries per page
function index() {
$this->Product->recursive = 0;
// works up to here fine
$this->set('products', $this->paginate()); // makes the browser hangs
}
}
When I go to ../products/index the browser just kind of hangs. It tries to load for minutes without giving any error messages, and I'm forced to restart Apache (XAMPP) or wait out a 60 seconds. The problem seems to be with $this->paginate() and all of the associations with Product controller. It has 2 belongsTo (belongs to smaller tables) and 1 hasOne (has one large table, 20K+ rows).
I added a hasOne relationship to the product model, and this seems to be causing the hanging. When I remove this relationship, the URL works and displays all items. However, this hasOne relationship does not cause any errors when I do for example, ../products/view/1.
Any idea on how to make this manageable?
There are a few things you can look at to start debugging. The first is your logs. Check both SQL and PHP logs for slow queries and timeout errors respectively.
If your Product model has a lot of associations, I suggest using ContainableBehavior. Actually, I suggest always setting $recurisve = -1; on the model and using Containable to fetch associations. It will speed up your app dramatically. Why pull data you don't use in your views?
In your app_model, add the behavior:
class AppModel extends Model {
var $recursive = -1;
var $actsAs = array('Containable');
}
Then modify your find queries to grab the associated data that you want:
$this->Product->find('all', array(
'contain' => array
'Category',
'Type'
)
));
Where Category and Type are associated with Product. This will tell Cake to just pull that associated data.
Then look at your queries. Use DebugKit to help you analyze timing and slow queries.
These are some basic methods for speeding up your finds. There's a ton of information out there for optimizing your CakePHP app, which is what sounds like may be the problem.
OK, I am a little bit lost...
I am pretty new to PHP, and I am trying to use CakePHP for my web-site.
My DB is composed of two tables:
users with user_id, name columns
copies with copy_id, copy_name, user_id (as foreign key to users) columns.
and I have the matching CakePHP elements:
User and Copy as a model
UserController as controller
I don't use a view since I just send the json from the controller.
I have added hasMany relation between the user model and the copy model see below.
var $hasMany = array(
'Copy' => array(
'className' => 'Friendship',
'foreignKey' => 'user_id'
)
);
Without the association every find() query on the users table works well, but after adding the hasMany to the model, the same find() queries on the users stop working (print_r doesn't show anything), and every find() query I am applying on the Copy model
$copy = $this->User->Copy->find('all', array(
'condition' => array('Copy.user_id' => '2')
));
ignores the condition part and just return the whole data base.
How can I debug the code execution? When I add debug($var) nothing happens.
I'm not an expert, but you can start with the following tips:
Try to follow the CakePHP database naming conventions. You don't have to, but it's so much easier to let the automagic happen... Change the primary keys in your tabel to 'id', e.g. users.user_is --> users.id, copies.copy_id -->copies.id.
Define a view, just for the sake of debugging. Pass whatever info from model to view with $this->set('users', $users); and display that in a <pre></pre> block
If this is your first php and/or CakePHP attempt, make sure you do at least the blog tutorial
Make CakePHP generate (bake) a working set of model/view/controllers for users and copies and examine the resulting code
There's good documentation about find: the multifunctional workhorseof all model data-retrieval functions
I think the main problem is this:
'condition' => array('Copy.user_id' => '2')
It should be "conditions".
Also, stick to the naming conventions. Thankfully Cake lets you override pretty much all its assumed names, but it's easier to just do what they expect by default.
The primary keys should be all named id
The controller should be pluralised: UsersController
First off, try as much as possible to follow CakePHP convention.
var $hasMany = array(
'Copy' => array(
'className' => 'Friendship',
'foreignKey' => 'user_id'
)
);
Your association name is 'Copy' which is a different table and model then on your classname, you have 'Friendship'.
Why not
var $hasMany = array(
'Copy' => array('className'=>'Copy')
);
or
var $hasMany = array(
'Friendship' => array('className'=>'Friendship')
);
or
var $hasMany = array(
'Copy' => array('className'=>'Copy'),
'Friendship' => array('className'=>'Friendship')
);
Also, check typo errors like conditions instead of condition
Your table name might be the problem too. I had a table named "Class" and that gave cake fits. I changed it to something like Myclass and it worked. Class was a reserved word and Copy might be one too.