Hey I have coded CakePHP for a number of things but never ran into this problem before surprisingly. Also I have thoroughly searched the net and CakePHP docs and have not found an answer to my question. My question is, I have a table for my model that should be named Class, obviously I cannot use that name though since it's a reserved PHP keyword. What options do I have to be able to refer to this model appropriately.
So far I have;
Renamed my class model file to player_class.php
Renamed my class model class to PlayerClass
Changed var $name to 'PlayerClass'
Added to my class model class; var $useTable = 'classes';
Renamed my class controller to player_classes_controller.php
Renamed my class controller class to PlayerClassesController
Changed var $name to 'PlayerClasses'
While this does work, is this what has to be done or are to other options to be able to refer to it as Class still, like can I do any sort of mangling like _Class?
I once tested all CakePHP class names for Cake 1.2 if they can be used as Model names, here are the results:
NOT possible is:
app
appcontroller
appmodel
behaviorcollection
cache
cacheengine
cakelog
cakesession
classregistry
component
configure
connectionmanager
controller
datasource
debugger
dispatcher
file
fileengine
folder
helper
inflector
model
modelbehavior
object
overloadable
overloadable2
router
security
sessioncomponent
set
string
validation
Possible is:
acl
aclbase
aclbehavior
aclcomponent
aclnode
aclshell
aco
acoaction
admin
ajaxhelper
apcengine
apishell
app_model
apphelper
aro
authcomponent
bake
baker
bakeshell
behavior
cachehelper
cake
cakeschema
cakesocket
consoleshell
containablebehavior
controllertask
cookiecomponent
dbacl
dbaclschema
dbconfigtask
dboadodb
dbodb2
dbofirebird
dbomssql
dbomysql
dbomysqlbase
dbomysqli
dboodbc
dbooracle
dbopostgres
dbosource
dbosqlite
dbosybase
element
emailcomponent
error
errorhandler
extracttask
flay
formhelper
htmlhelper
httpsocket
i18n
i18nmodel
i18nschema
i18nshell
iniacl
javascripthelper
jshelper
jshelperobject
l10n
layout
magicdb
magicfileresource
mediaview
memcacheengine
modeltask
multibyte
numberhelper
page
pagescontroller
paginatorhelper
permission
plugintask
projecttask
requesthandlercomponent
rsshelper
sanitize
scaffold
schema
schemashell
securitycomponent
sessionhelper
sessionsschema
shell
shelldispatcher
test
testsuiteshell
testtask
texthelper
themeview
timehelper
translate
translatebehavior
treebehavior
viewtask
xcacheengine
xml
xmlelement
xmlhelper
xmlmanager
xmlnode
xmltextnode
When i run into this sort of problem i usually do what you did, only i prefix the reserved word with "My" (so when i read the code it doesn't look like that class has anything to do with "Player"... for example, just the other day i wanted to model a "ACO" model.. but that already existed in cake (same scenario of reserved word) so i created a model called Myaco.
I think you should just name it Myclass.
Regarding the model name and controller name changes- i think you did good, i would do the same. Your only real option is to use the $useTable = 'classed'; to use your DB table.
If you use the underscore prefix, i believe cake will not be able to handle it (it will fail in the Inflector class).
Good luck
I can second that solution. I had the same problem and used a prefix that was the initials of the client. Ended up calling mine Dtclass. Unfortunately, it took me an hour or so to figure out what the problem was. One of those cases where the answer stares you in the face all the time till you finally recognize it.
Related
I have a simple problem and I don't know how to solve it.
I work with an existing database, where tables don't match with cakePHP conventions, and I have to make cakePHP work with it.
For example, I have a table named "ItiConf" in sql db (instead of iti_confs by convention).
My model ItiConfModel.php :
class ItiConf extends AppModel {
}
My controller ItiConfsController.php :
class ItiConfsController extends AppController {
//...
}
I tried to make my own Inflector::rules in app/Config/bootstrap.php file,
but it doesn't work and I still have the following error :
*Error: Table iti_confs for model ItiConf was not found in datasource default.*
Do you please have any idea or hint about this problem and the synthax of the related inflector rule needed ?
Thanks you by advance !
Inset07.
While Cake has its conventions, it doesn't require them to be used. In this case, try the $useTable property to change the table the model uses, instead of modifying Inflector rules:
class ItiConf extends AppModel {
public $useTable = 'ItiConf';
}
More info here: http://book.cakephp.org/2.0/en/models/model-attributes.html#usetable
I am using CakePHP 2.x
There are several database tables setup :
1) Fruit
2) Vege
3) Drink
I am able to access these database tables in a CONTROLLER using this line below. With this line, I am able to access these other tables.
public $uses = array('Get', 'Fruit', 'Vege', 'Drink');
My problem is when trying to access them in a MODEL. When I try this code below, an error occurs.
App::uses('AppModel', 'Model');
class Get extends AppModel {
public function getHistory( $limit ) {
$searchLimit = $limit;
$raw = $this->Fruit->find('all')
An error occurs at the line '$this->Fruit'.
Call to a member function find() on a non-object...
Any ideas how to call multiple database tables in a single MODEL ?
As accessing all the database tables work perfectly in the CONTROLLER, I did this in the CONTROLLER instead of the MODEL. It seems much easier and straight forward to do this in CONTROLLER.
A private function is created in the CONTROLLER, and accessed by other functions using '$this->myPrivateFunctionName()'
First you should read on model associations Model associations
Second, if that doesn't fit your needs (meaning there is no clear association between models, honestly I don't see connection between Get and Fruit) you can use ClassRegistry:
$Fruit = ClassRegistry::init('Fruit');
Before you can use ClassRegistry you must add this before class definition:
App::uses('ClassRegistry', 'Utility');
Associate model by $belongsTo, $hasMany or what ever relation you want.
than access by $this->Fruit->find()
I am building a new app based on multiple databases with many tables which don't follow any Cake conventions. I want to use CakePHP but I'm not sure if it's possible without the database in a Cake format.
Problems include:
Tables not named as Cake expects
Primary keys are not necessarily named id (e.g. it might be order_id)
Foreign keys are not necessarily named like other_table_id
Changing the database tables is not an option.
Is it possible to manually configure the schema in each model so that Cake will then know how the model relationships need to work? Or should I just give up on using Cake?
yes. you can still use CakePHP in your case.
Check out various Model attributes to fit your needs
http://book.cakephp.org/2.0/en/models/model-attributes.html.
e.g.
public $useTable = 'exmp' can be used to configure what table to use.
public $primaryKey = 'example_id'; can be used to configure the primary key's name
**Try this code sample............**
More detail here http://book.cakephp.org/2.0/en/models/model-attributes.html
<?php
class Example extends AppModel {
// Name of the model. If you do not specify it in your model file it will be set to the class name by constructor.
public $name = 'Example';
// table name example
public $useTable = example;
// example_id is the field name in the database
public $primaryKey = 'example_id';
}
?>
I'm using the following code in my bootstrap.php (as explained here) to load models also from another folder:
App::build(array('Model' => array('/my/path/to/models')));
This seems to work. I have a model MyModel inside that folder, which I include in the controller I want to use it like usually:
var $uses = array('MyModel');
If I print App::objects('Model'), the model MyModel is shown in the list, so I assume it's loaded correctly. However, when I try to use the model (i.e. $this->MyModel->find() it never finds anything, it always returns an empty array.
Note that if I put the same exact model (MyModel) in the typical models folder (app/Model/) then it all works fine.
What am I missing to make this work?
EDIT
Ok, so it seems that the problem is in the connection to the database when the model is placed in that folder outside app. With the code shown above, Cake finds the model. However, when I do a find(), I get a missing table error for the datasource (default in this case).
Is it possible that the model isn't loading the correct database configuration because that configuration is inside the app/Config folder? How can I make that model load that configuration? If I have to put that configuration somewehre else (maybe in the same outside folder?) I can do that, but how do I tell the model to find it?
EDIT 2
I can see better what the problem is now. If I put a model in a different folder (other than app/Model) and use App::build() to set the path of that new folder, Cake finds it, there's no doubt (I use App::objects('Model') and the model is listed with all the other models from app/Model).
However, it's like Cake is not actually reading what's inside that model class, or at least not everything. It seems to read the $useDbConfig variable, but it ignores $useTable and any function I have defined in that model. Example of my model:
class Usuario extends AppModel {
var $name = 'Usuario';
var $primaryKey = 'id_usuario';
var $useDbConfig = 'BD_ControlAcceso';
function createTempPassword($len) {
//some code
}
}
If I do a $this->Usuario->find('all'), it returns all the records correctly. However, if I call $this->Usuario->createTempPassword(7) I get a Database Error.
I have another model (MyModel) in that same folder with a $useTable = 'mytable'. If I don a find() on it, I get an error saying that mytable table could not be found. However, if I do $this->MyModel->useTable = 'mytable' then it works fine.
How is this possible? What's going on here?
EDIT 3
I just want to add that I've done extensive testing and the issue is clear: Cake "knows" that the model is in the external folder (confirmed by printing App::objects('Model'), the model is listed there, and if I remove it from that folder then it's not listed). But even though it knows it's there, it ignores whatever is inside the model file. I've tried all the methods below to load the model but none of them worked. Is this a bug in CakePHP? If not, what am I doing wrong?
You should use App::uses('MyModel', 'Model') and is should go before the class declaration like so:
<?php
App::uses('MyModel', 'Model');
App::uses('AppController','Controller');
class UsersController extends AppController {
// controller class
}
Another thing to try is loading the model where you need it:
$this->loadModel('MyModel');
The other thing you can try is the Model instantiation in the top of your model class. Try updating your model to:
App::uses('AppModel','Model');
class Usuario extends AppModel {
var $name = 'Usuario';
var $primaryKey = 'id_usuario';
var $useDbConfig = 'BD_ControlAcceso';
function createTempPassword($len) {
//some code
}
}
I have the following test case in my CakePHP (2.0.1) app:
<?php
public function testGetTenUsers() {
$users = $this->User->find('all' , array('limit' => 10));
// .... assert some things
}
?>
This works fine, and returns 10 records from my fixture.
When I add the Translate behaviour to my User model, this test no longer works (returns empty array).
Not sure how to approach this. Do I create an I18n fixture, or unbind the behaviour?
Any help appreciated.
Like you just stated, the best solution is to create a fixture.
Unbinding this behavior will make your tests less likely to catch errors. My point is: The further you are from your production configuration, the more complex it becomes to find bugs and quirks.
Here is my default fixture for i18n:
<?php
// I'm working in CakePHP 1.3 at the moment
class I18nFixture extends CakeTestFixture {
public $name = 'I18n';
public $table = 'i18n';
public $import = array(
'table'=>'i18n',
'records'=>true
);
}
I imported the rows in my i18n table from the default configuration, because I only have static content in it (i.e. translation for types, roles). I wouldn't recommend doing this if you have many user input stored in it.
Please also note that you have to specify the table name in the fixture if you want to avoid the inflector to kick in. (so your table name stays "i18n" and not "i18ns")