CakePHP doens't support load models? - cakephp

I use CakePHP 1.3.9 but I can't use other Models in a Controller.
I use $this->loadModel('ModelName); and $this->ModelName->find('all') - always empty.
The variable $uses also doesn't work.
Why is it not working for me?
I used i18n and must set $locale...

Do you mean the data set is empty? If the model is not loaded, you shouldn't be able to call $this->ModelName->find() as $this->ModelName would be null. Does it throw an error? Your usage is correct, as stated in the manual : http://book.cakephp.org/view/992/loadModel
You can also do
App::import('Model', 'ModelName');
$model = new Model();
But I'm guessing that your current resultset is returning empty rather than the model itself not being set.
Have you tried looking at what $this->ModelName actually contains? Do the following and post it here
pr($this->ModelName)

It's considered bad practice to put (un-associated) models in your $uses array.
Depending what you are trying to do, you may be able to make use of containable behaviour.
$this->User->Post->find('all');
If not, you should be able to use loadModel:
$this->loadModel('Article');
$recentArticles = $this->Article->find('all', array('limit' => 5));
To quote Cake:
The loadModel function comes handy when you need to use a model which is not the controller's default model or its associated model.

JohnP and Ross are correct. Controller::loadModel() is clearly working and not your problem if pr($this->ModelName) is working for you.
As they mentioned, you're probably having trouble because the data simply isn't in the database. Or maybe there's something wrong with your query. Have you tried checking the query that's produced by CakePHP and trying to query the database directly through the MySQL command line (assuming you're using MySQL)?
Or is there any chance you've overloaded the Model::find() method?

Related

How to choose the test DB cakePHP testing

I am using the cake bake command to create my fixture and Test models. I have done it successfully with one of my models but i am having troubles with another one.
I dont know why, it tries to work with the default DB instead with the test one that i have already defined and that is the one used by the first model i tested.
Both Test models, the one which works well and this 2nd one which doesn't, have been created with cake bake and they look exactly the same.
Both of them have this in their fixture class:
public $import = array('records' => true, 'connection' => 'test');
Test defines the connection to my test database.
What can be the problem?
I have experiment something weird. In my test model if i use the singluar instead of the plural, it works with the default DB BUT if i change it to plural it works with the test DataBase. (but it can not call any method from the model, just defined methods such as find()).
For example:
public function setUp() {
parent::setUp();
//uses the default DB (i dont know why)
$this->Post = ClassRegistry::init('Post');
print_r($this->User->find('all'));
$this->Post->updatePostsStatus(1); //works well
//uses the default Test Database (i dont know why either)
$this->Post = ClassRegistry::init('Posts');
print_r($this->User->find('all'));
$this->Post->updatePostsStatus(1); //doesn't work. No function found.
/*SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'updatePostsStatus' at line 1*/
}
Thanks.
I HAVE UPDATED IT.
LAST UPDATE AND SOLUTION
The problem was the bad initialization of the Post Model constructor.
Using the plural was not relevant. It is like using any non existent model. It will always get the test database.
The answer for the good initialization of the constructor is here:
How to override model's constructor correctly in CakePHP
That sort of MySQL error can be very misleading in CakePHP.
Basically the actual problem is with the line $this->Post->updatePostsStatus(1); Specifically it's that eitherthe Post model or updatePostsStatus() method of the posts model doesn't exist.
You basically have a typo on this line, check the method name. Should it be updatePostStatus? (no plural on posts?)
For some reason, if you try to call an undefined method on a model in CakePHP, instead of reporting the method is not found, the "automagicness" of CakePHP kicks in and bizarrely it tries to push the unfound method name straight into MySQL.
Basically, because CakePHP cannot find the $this->Post->updatePostsStatus(1); method, it is actually trying to execute a MySQL query of updatePostsStatus ie mysql_query("updatePostsStatus');, which is why we are seeing this wierd database error. Chances are you've just misspelled the method name.
If the method name is still not the problem, it's something to do with the Posts model not being instantiated correctly. Although that seems doubtful as long as you got all the names right. It is definitely not a database issue, just Cakes lame way of handling unknown class methods automagically.

CakePHP Media Plugin Helper problem

I am trying to display an uploaded image with the Media Plugin of CakePHP.
I added the helper to the controller helper array: var $helpers = array('Media.Media');. Then, in my view, I have this code: echo $media−>file($news['Attachment'][0]['dirname'].DS.$news['Attachment'][0]['basename']);. But the problem is that, it outputs this error:
Undefined variable: media− [APP/views/news/view.ctp, line 3]
What could be the problem?
By the way, if a plugin has a model User in app/plugin/users/models/user.php and i create a new model called User in the app/models folder which one will be loaded?
Thanks in advance for any help!
First off if you are using 1.3.x refer to helpers via $this->HelperName->method(), there could be a variable called $media being set in some method. you can check this by doing var_dump($media);
The other option is that something has maybe unset it. Its very strange that you have the helper set but the variable is not set. It could also be due to adding the $helpers array to the wrong controller, you can try add it to app_controller and see if that works. if it does you had it in the wrong place.
If i got your second question correct, and we are talking about auto loading, a plugin controller will first look for the model in its own plugin directory, if it is not found there it will fall back to the app/models directory.
if you are loading it manually via the $uses array, it depends on the version of cake and how you do it. In previous versions 1.x even $uses = array('User'); would load the plugin model as cake would auto add the plugin prefix. This has changed for 2.0 afaik.
For other methods of loading a model, such as $this->loadModel('User); would load from app/models and $this->loadModel('PluginName.User') would load from the app/plugins/plugin_name/models dir.
Edit:
you are right that is funny having the error show $media- and there is the problem. did you copy that code from some site? − is not - you have a utf8 char in the code which is what its complaining about.

cakephp: can I set $scripts_for_layout from within a controller?

I'd like to set the layout's $scripts_for_layout from within the controller.
Is this possible, and if yes how?
Short answer: maybe you're doing it wrong.
Long answer: Scripts should not be controller dependent. It's 'theoretically' wrong, and cake does not like people who doesn't adhere to the mvc pattern.
Workaround (because sometimes you just need to): You can set in beforeRender a var:
function beforeRender() {
parent::beforeRender();
$this->set('scripts', array('script1', 'script2' ...));
}
And in the layout check for $scripts and add them.
In cake 1.2, when you do $this->set('script_for_layout', 'script here...), it will convert this variable to $scriptForLayout so it wouldn't work.
Cake 1.3 fixed this but I haven't tried to see if it works or not but you are violating MVC because script was meant for the View, not set at the Controller level. For dynamic script, you can assign variables to your view like the previous poster has suggested.
I know this is an old question, but I had the same issue today. The solution seems easier than the answers mentioned here. From CakePHP 1.2 cookbook:
inline: whether the block should be printed inline, or written to cached for later output (i.e. $scripts_for_layout).
So, in your view you just need to include scripts setting the inline as false, like this:
$javascript->link('script1', false)
You can do the same for CSS:
$html->css('stylesheet1', null, array(), false)
Attention : I only tested this on CakePHP 1.2. But according to cookbook for 1.3, it is the same thing.

cakephp and get requests

How does cakephp handle a get request? For instance, how would it handle a request like this...
http://us.mc01g.mail.yahoo.com/mc/welcome?.gx=1&.rand=9553121_pg=showFolder&fid=Inbox&order=down&tt=1732&pSize=20&.rand=425311406&.jsrand=3
Would "mc" be the controller and "welcome" be the action?
How is the rest of the information handled?
Also note that you could use named parameters as of Cake 1.2. Named parameters are in key:value order, so the url http://somesite.com/controller/action/key1:value1/key2:value2 would give a a $this->params['named'] array( 'key1' => 'value1', 'key2' => 'value2' ) from within any controller.
If you use a CNN.com style GET request (http://www.cnn.com/2009/SHOWBIZ/books/04/27/ayn.rand.atlas.shrugged/index.html), the parameters are in order of appearance (2009, SHOWBIZ, books, etc.) in the $this->params['pass'] array, indexed starting at 0.
I strongly recommend named paramters, as you can later add features by passing get params, without having to worry about the order. I believe you can also change the named parameter separation key (by default, it's ':').
So it's a slightly different paradigm than the "traditional" GET parameters (page.php?key1=value1&key2=value2). However, you could easily add some logic in the application to automatically parse traditional parameters into an array by tying into how the application parses requests.
CakePHP uses routes to determine this. By default, the routes work as you described. The remainder after the '?' is the querystring and it can be found in $this->params['url'] in the controller, parsed into an associative array.
Since I found this while searching for it, even though it's a little old.
$this->params['url']
holds GET information.
I have tested but it does work. The page in the Cakephp book for it is this link under the 'url' section. It even gives an example very similar to the one in the original question here. This also works in CakePHP 1.3 which is what I'm running.
It doesn't really use the get in the typical since.
if it was passed that long crazy string, nothing would happen. It expects data in this format: site.com/controller/action/var1/var2/var....
Can someone clarify the correct answer? It appears to me that spoulson's and SeanDowney's statements are contradicting each other?
Would someone be able to use the newest version of CakePHP and get the following url to work:
http://www.domain.com/index.php/oauth/authorize?oauth_version=1.0&oauth_nonce=c255c8fdd41bd3096e0c3bf0172b7b5a&oauth_timestamp=1249169700&oauth_consumer_key=8a001709e6552888230f88013f23d5d004a7445d0&oauth_signature_method=HMAC-SHA1&oauth_signature=0bj5O1M67vCuvpbkXsh7CqMOzD0%3D
oauth being the controller and authorize being a method AS WELL as it being able to accept the GET request at the end?

Why doesnt paginator remember my custom parameters when I go to page 2?

When using the paginator helper in cakephp views, it doesnt remember parts of the url that are custom for my useage.
For example:
http://example.org/users/index/moderators/page:2/sort:name/dir:asc
here moderators is a parameter that helps me filter by that type. But pressing a paginator link will not include this link.
The secret is adding this line to your view:
$paginator->options(array('url'=>$this->passedArgs));
(I created this question and answer because it is a much asked question and I keep having to dig out the answer since i cant remember it.)
To add to Alexander Morland's answer above, it's worth remembering that the syntax has changed in CakePHP 1.3 and is now:
$this->Paginator->options(array('url' => $this->passedArgs));
This is described further in the pagination in views section of the CakePHP book.
$this->passedArgs is the preferred way to do this from the view.
You saved me! This helped me a lot, Thanks.
I needed a way to pass the parameters I originally sent via post ($this->data) to the paging component, so my custom query would continue to use them.
Here is what I did:
on my view I put
$paginator->options(array('url'=>$this->data['Transaction']));
before the $paginator->prev('<< Previous ' stuff.
Doing this made the next link on the paginator like "
.../page:1/start_date:2000-01-01%2000:00:00/end_date:3000-01-01%2023:59:59/payments_recieved:1"
Then on my controller I just had to get the parameters and put them in the $this->data so my function would continue as usual:
foreach($this->params['named'] as $k=>$v)
{
/*
* set data as is normally expected
*/
$this->data['Transaction'][$k] = $v;
}
And that's it. Paging works with my custom query. :)
The options here are a good lead ... You can also check for more info on cakePHP pagination at cakephp.org/view/166/Pagination-in-Views
With that param 'url' you can only put your preferred string before the string pagination in url..
if I use this tecnique:
$urlpagin = '?my_get1=1&my_get2=2';
$paginator->options = array('url'=>$urlpagin);
I only obtain:
url/controller/action/?my_get1=1&my_get2=2/sort:.../...
and Cake lost my get params
Have you an alternative tecnique?

Resources