I am having a problem using the create() method in the cakephp. I have the following code and when I run it in debug it just resumes the program when I try to step through it after the create line.
$this->CompanyDeviceQuestionConcern->create();
$this->CompanyDeviceQuestionConcern->set('source_company_id', $company_id);
$this->CompanyDeviceQuestionConcern->set('user_id', $user['id']);
$this->CompanyDeviceQuestionConcern->set('create_date', date('Y-m-d H:i:s'));
$this->CompanyDeviceQuestionConcern->set('modified_date', date('Y-m-d H:i:s'));
Does anyone know why it crashes when I run the first line?
I am not sure but i think your database refuses the create action because of limitations of some fields(like NOT NULL).
There is a workaround for this:
$newData = array(
'id' => NULL,
'source_company_id' => $company_id,
'user_id' => $user['id'],
'create_date' => date('Y-m-d H:i:s'),
'modified_date' => date('Y-m-d H:i:s')
);
$this->CompanyDeviceQuestionConcern->save($newData);
I found the silly mistake. I forgot to include the model in $uses variable in the class at the top. It is rather inconvenient that it doesn't show any type of error however.
Here is what I added to fix it.
class ReviewsController extends AppController {
var $uses = array('Question', 'CompanyTemplateGroupQuestionConcern');
Also if anyone wants any more information on how to uses works you can look here
http://book.cakephp.org/2.0/en/core-utility-libraries/app.html
Related
Using CakePHP 1.3 I created a small application which has a FooController. In this FooController I am using the Paginator to deliver the content of Foo to its views.
In the head of the FooController class I customized the preparation of the data from Foo like this:
var $paginate = array(
'limit' => 100,
'order' => array('Order.created' => 'desc'));
Now I would like to put the value for 'limit' into a configuration file.
So I created a file $config['list_length'] = '500'; in the config directory which I load in bootstrap.php. That works fine, I can echo the value of list_length, for example in the beforeFilter() of the class.
But I fail to make the Paginator use that value.
First I tried:
var $paginate = array(
'limit' => Configure::read('list_length'),
'order' => array('Order.created' => 'desc'));
But that fails with the following PHP error:
Parse error: syntax error, unexpected '(', expecting ')' in xyz/app/controllers/foo_controller.php on line 9
Then I tried:
public function beforeFilter() {
parent::beforeFilter();
$paginate['limit'] = Configure::read('list_length');
}
But it would still use the value '100' instead of '500'.
I guess this is a rather trivial problem that really comes from the fact that I am not very proficient with basic PHP concepts. I don't have much opportunity to get to program a little bit in my current job, so I'm really out of practice.
I would very much appreciate any hint on how to do this and even more on what concept I am missing here, so I could read a little bit about it.
You almost got it right;
The reason PHP is giving you the error in your first example is that class properties cannot be set using 'dynamic' values; from the documentation:
This declaration may include an initialization, but this initialization must be a constant value--that is, it must be able to be evaluated at compile time and must not depend on run-time information in order to be evaluated.
http://www.php.net/manual/en/language.oop5.properties.php
If you need to set a property to a value that is 'dynamic' (e.g. The result of a function), you will need to assign if from within a class 'method'
You tried to do this in your second example, however, properties of a class/object should be accessed using $this->nameOfTheProperty to indicate it is not a 'variable', but a 'property' of the object;
public function beforeFilter() {
parent::beforeFilter();
$this->paginate['limit'] = Configure::read('list_length');
}
Hope this helps
I am using CakePHP 2.1.3; I want to create a virtual field dynamically in a controller. Is it possible?
The problem is when I am trying to find max value in a table it gives me another array from the model array. Please ask if you need more information.
When I am trying to execute the following query,
$find_max_case_count = $this->CaseMaster->find('first', array(
'conditions' => array(
'CaseMaster.CLIENT_ID' => $client_id,
'CaseMaster.CASE_NO LIKE' => '%-%'
),
'fields' => array('max(CaseMaster.CASE_NO) AS MAX_NO')
));
It is giving me an array like:
[0]=> array([MAX_NO]=> 52)
However I want it to be like as:
[CaseMaster] => array([MAX_NO] => 52)
I found a solution. I can make the virtual field at runtime. The code should looks like:
$this->CaseMaster->virtualFields['MAX_NO'] = 0;
Write it just above the find query and the query will remain same as it was written.
This link was helpful to find out the solution.
There is no way (as far as I am knowledgeable) to create virtual fields "on the fly". What virtual fields are is "arbitrary SQL expressions" that will be executed when a find runs through the Model and "will be indexed under the Model's key alongside other Model fields".
What do you need to do with "dynamically created virtual fields"? If you explain what exactly you need to accomplish maybe we can provide a different (even more suitable? :) ) solution? I'd personally be happy to help you.
After you editing your question I can say that what you're getting is the way the array should be returned, this is because of the fields parameter. If you want to get a different structure out of it I suggest applying a callback to format it.
Firstly move the method inside the CaseMaster Model:
public function getMaxCaseCount($client_id){
$data = $this->find('first', array(
'conditions' => array(
'CaseMaster.CLIENT_ID' => $client_id,
'CaseMaster.CASE_NO LIKE' => '%-%'),
'fields' => array('max(CaseMaster.CASE_NO) AS MAX_NO')));
return array_map(array('CaseMaster', '__filterMaxCaseCount'), $data);
}
private function __filterMaxCaseCount($input){
//This is just an example formatting
//You can do whatever you would like here.
$output['CaseMaster'] = $input[0];
return $output;
}
The array_map function will apply the __filterMaxCaseCount callback method so that when you call:
$this->CaseMaster->getMaxCaseCount($client_id);
from your controller you will get the data in the way you need it. The array_map function could also look like this:
return array_map(array($this, '__filterMaxCaseCount'), $data);
because you're in the same Class.
Just adding your model alias to field definition also works for this purpose
'fields' => array('max(CaseMaster.CASE_NO) AS CaseMaster__MAX_NO')
I have a model with the name Deal class Deal extends AppModel
Now in my controller I call a method in the Deal model called getDeal()
$dealInfo = Deal::getDeal($dealID);
I want the info returned to me but the var_dump displays blank
function getDeal($dealID){
$deal = $this->Deal->find('first', array(
'conditions' =>
'Deal.id' =>$dealID
) ,
'fields' => array(
'Deal.id'
) ,
'recursive' => 1,
));
}
This is the first time I'm working in cakePHP, so this question might sound a bit dumb
When you're just using an id as your find condition you can use CakePHP's dynamic finder methods.
Dynamic finders work like this.
$this->Model->findByModelFieldName();
In your example it would be
$this->findById($dealId, array(
'fields' => array('Deal.id'),
'recursive' => 1
));
I don't know if I'm just being mental, but is this simply because you're not returning anything from getDeal()?
Try adding return $deal; and see if that helps. Your question doesn't state exactly where you're doing the var_dump so I might be well off.
Edit:
As per the discussion with you and 8vius, we've established that this isn't right, and you simply need to change $this->Deal->find() to $this->find() because its being run from the model.
Check your function declaration, $deal_id does not exist and as you can see from the parameter you pass to the function which should me $deal_id and not dealID. So you have a misdeclared function calling find with a variable that does not exist.
I am working on a book review application and I am using autoComplete to search for titles in when creating a review. The review model has an associated book_id field and the relationship is setup as the review hasOne book and a book hasMany reviews.
I am trying to pass the Book.id (into the book_id field), but I want to display Book.name for the user to select from. With the default setup (accomplished via CakePHP's tutorial), I can only pass Book.name. Is it possible to display the name and pass the id?
Also, I am passing it via the following code in the create() action of the review controller:
$this->data['Review']['book_id'] = $this->data['Book']['id'];
Is that the proper way to do it in CakePHP? I know in Ruby on Rails, it is automatic, but I can't seem to make it work automagically in CakePHP. Finally, I am not using the generator because it is not available in my shared hosting environment... so if this is the wrong way, what do I need other than associates in my models to make it happen automatically?
Thanks for the help and I promise this is my question for awhile...
UPDATE- I tried the following, but it is not working. Any ideas why?
function autoComplete() {
$this->set('books', $this->Book->find('all', array(
'conditions' => array(
'Book.name LIKE' => $this->data['Book']['name'].'%'
),
'fields' => array('id','name')
)));
$this->layout = 'ajax';
}
The problem is that when I use the code above in the controller, the form submits, but it doesn't save the record... No errors are also thrown, which is weird.
UPDATE2:
I have determine that the reason this isn't working is because the array types are different and you can't change the array type with the autoComplete helper. As a workaround, I tried the follow, but it isn't working. Can anyone offer guidance why?
function create() {
if($this->Review->create($this->data) && $this->Review->validates()) {
$this->data['Review']['user_id'] = $this->Session->read('Auth.User.id');
$this->Book->find('first', array('fields' => array('Book.id'), 'conditions' => array('Book.name' => $this->data['Book']['name'])));
$this->data['Review']['book_id'] = $this->Book->id;
$this->Review->save($this->data);
$this->redirect(array('action' => 'index'));
} else {
$errors = $this->Review->invalidFields();
}
}
FINAL UPDATE:
Ok, I found that the helper only takes the find(all) type or array and that the "id" field wasn't passing because it only applied to the autoComplete's LI list being generated. So, I used the observeField to obtain the information and then do a database lookup and tried to create a hidden field on the fly with the ID, but that didn't work. Finally, the observeField would only take the characters that I put in instead of what I clicked, due to an apparent Scriptaculous limitation. So, I ended up going to a dropdown box solution for now and may eventually look into something else. Thanks for all of the help anyway!
First of all, $this->data will only contain ['Book']['id'] if the field exists in the form (even if it's hidden).
To select something by name and return the id, use the list variant of the find method, viz:
$selectList = $this->Book->find('list', array(
'fields' => array(
'id',
'name'
)));
$this->set('selectList', $selectList);
In the view, you can now use $selectList for the options in the select element:
echo $form->input('Book.id', array('type' => 'hidden'));
echo $form->input('template_id', array(
'options' => $selectList,
'type' => 'select'
));
I'm following the ACL tutorial for CakePHP 1.3 and I was wondering if there is a functional difference between declaring a behavior like this:
var $actsAs = array('Acl' => 'requester');
and like this:
var $actsAs = array('Acl' => array('type' => 'requester'));
Though your two examples are both valid and correct for CakePHP 1.3.4 (cake/libs/model/behaviors/acl.php lines 48-51), the suggested third method posted by bancer is not correct. Because the AclBehavior defaults to 'requester' when it cannot find the configuration, this is a potentially frustrating bug in that it will work as expected until you attempt to change the type to 'controlled'. (it also doesn't work in CakePHP 1.2 - Mark Story made a change to that line at the advice of an anonymous user.) If you do want to replace your third example, var $actsAs = array('Acl'); should do fine (unless you want type to be 'controlled', but you can then see to add the option).
There is no difference. You can even declare this way:
var $actsAs = array('Acl' => array('requester'));