CakePHP - Only one Query from external Model - php

I've two Models:
class Post extends AppModel {
var $name = 'Post';
var $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'user_id'
)
);
}
and
class User extends AppModel {
var $name = 'User';
var $hasMany = 'Post';
}
Now I'm having a problem with a query in the PostsController. I've an add() function and the view add.ctp which is basically a form. Now I would like to show some User information in that form.
class PostsController extends AppController {
var $name = 'Posts';
var $helper = array('Html', 'Form');
var $uses = array('User');
public function index() {
$this->set('posts', $this->Post->find('all'));
}
function add() {
$user_id = 1;
$this->set('user', $this->User->findById($user_id));
if ($this->request->is('post')) {
if ($this->Post->save($this->request->data)) {
$this->Session->setFlash('Your post has been saved.');
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash('Unable to add your post.');
}
}
}
}
But now the add-view-page shows that actually two queries where triggered. So if I print_r($user) within the add-view I'm getting an array with two arrays. One for a Post with user_id = 1 and one for the actual User with id = 1. But I would like to get only the User id = 1.

Try setting recursive to false on the User model before calling findById, so you won't get any data from associated models. Like this:
function add() {
$user_id = 1;
$this->User->recursive = false;
$this->set('user', $this->User->findById($user_id));
if ($this->request->is('post')) {
if ($this->Post->save($this->request->data)) {
$this->Session->setFlash('Your post has been saved.');
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash('Unable to add your post.');
}
}
}

Related

How to fix approval system in CakePHP

I made a blog and I can leave comments to my articles, then I made an Approve button, need to make the approve function.
I need to make it to work. I just can't, no matter what I try. I want to be able to approve or not a comment before it's posted. I have tried everything I could think of.
<?php
namespace App\Controller;
class CommentsController extends AppController
{
public function index()
{
$comments = $this->Comments->find('all');
$this->set(compact('comments'));
}
public function view($id = null)
{
$comment = $this->Comments->get($id);
$this->set(compact('comment'));
}
public function add()
{
$comment = $this->Comments->newEntity();
if ($this->request->is('post')) {
$comment = $this->Comments->patchEntity($comment, $this->request->data);
$comment->user_id = $this->Auth->user('id');
$comment->aproved = 0;
$comment->article_id = $this->request->data['article_id'];
if ($this->Comments->save($comment)) {
$this->Flash->success(__('Your comment has been saved.'));
return $this->redirect(['controller' => 'Articles', 'action' => 'view', $comment->article_id]);
}
$this->Flash->error(__('Unable to add your comment.'));
}
$this->set('comment', $comment);
}
public function aprove()
{
}
}
Try this
Your link should look like this:
$this->Html->link('approve', array('controller' => 'your-controller', 'action' => 'aprove', $comment_id, $value['Comment']['aproved']));
and your controller function is:
public function aprove($comment_id, $approve_value)
{
if(isset($comment_id) && !empty($comment_id)){
$approve = $this->Comments->find('first',array('conditions'=>array('id'=>$comment_id),'fields'=>array('Comment.id, Comment.approve')));
if(!empty($approve)){
$this->Comments->id = $approve['Comment']['id'];
$this->Comments->saveField('aproved', $approve_value);
}
}
}

how to insert values in table in cake php

here i done code for contact us page with two fileds like email,body it stores values in db
but it s not working i post the code here
Model
//model/pages.php
<?php
class pages extends AppModel{
var $useTable = 'contact';
}
?>
Controller
class PagesController extends AppController {
public $uses = array();
public function display() {
$path = func_get_args();
$count = count($path);
if (!$count) {
return $this->redirect('/');
}
$page = $subpage = $title_for_layout = null;
if (!empty($path[0])) {
$page = $path[0];
}
if (!empty($path[1])) {
$subpage = $path[1];
}
if (!empty($path[$count - 1])) {
$title_for_layout = Inflector::humanize($path[$count - 1]);
}
$this->set(compact('page', 'subpage', 'title_for_layout'));
try {
$this->render(implode('/', $path));
} catch (MissingViewException $e) {
if (Configure::read('debug')) {
throw $e;
}
throw new NotFoundException();
}
}
public function index(){
$this->set('post', $this->contact->find('all'));
}
public function create() {
if ($this->request->is('post'))
//this function for methods like get, post, set,delelte
{
// print_r('post');
$this->contact->create();
if ($this->contact->save($this->request->data)) {
$this->Session->setFlash(__('Your post has been saved.'));
return $this->redirect(array('action' => 'index'));
}
$this->Session->setFlash(__('Unable to add your post.'));
}
}
}
view
here code for display
view/contact.ctp
<?php
echo 'welcome to Contact us';
echo $this->Form->create('pages');
echo $this->Form->input('email');
echo $this->Form->input('body', array('rows' => '6'));
echo $this->Form->end('Save pages');
?>
added in db table and values contact
Did you read something to start in CakePHP like Getting Started or CakePHP Conventions?
Reading some documentation, you will find that your tables should be named in plural and models in singular. Your model in app/Model/Contact.php looks like this:
class Contact extends AppModel {
public $useTable = 'contacts'; // It is not necessary, because CakePHP implicitly understands that your table will be in the plural
}
Now, your view located in app/View/Contacts/index.ctp:
echo $this->Form->create('Contact');
echo $this->Form->input('email');
echo $this->Form->input('body', array('rows' => '6'));
echo $this->Form->end('Save');
And your controller in app/Controller/ContactsController.php:
class ContactsController extends AppController {
public function index() {
if ($this->request->is('post')) {
$this->Contact->create();
if ($this->Contact->save($this->request->data)) {
$this->Session->setFlash(__('Your contact has been saved.'));
} else {
$this->Session->setFlash(__('Unable to add your contact.'));
}
}
}
}
This is a basic usage. I recommend you read the documentation to start with CakePHP because it has lots of interesting things that you may need.

How to create multiple objects in add method of controller with CakePHP

I have a ProductsController with an add view that as an autocomplete field ('brand_name') on it where the user can enter a brand name.
In my handler I want to check if the brand name already exists in the database, the brand_id should be set on the product. If it does not exists in the database, a new Brand should be created and inserted in the database.
The code beneath is simplified:
app/Model/Product.php
class Product extends AppModel {
public $belongsTo = array('Brand');
}
app/Controller/ProductsController.php
class ProductsController extends AppController {
public $helpers = array('Html', 'Form', 'Session');
public $components = array('Session');
public function add() {
if ($this->request->is('post')) {
$this->Product->create();
$brand = $this->Product->Brand->find(
'first',
array(
'conditions' => array(
'Brand.name' => $this->request->data['Product']['brand_name']
)
)
);
if($brand)
{
$this->request->data['Product']['brand_id'] = intval($brand['Brand']['id']);
}
else
{
// Add new brand
//$this->Product->Brand->create();
$this->Product->Brand->name = $this->request->data['Product']['brand_name'];
}
if ($this->Product->saveAll($this->request->data)) {
$this->Session->setFlash(__('The product has been saved.'));
//$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('Unable to add the product.'));
}
}
}
}
Everything works fine, except for creating and inserting the new Brand object. How do I create this object in code?
I'm brand new to CakePHP so if my approach is wrong, please let me know.
I've fixed this by adding a new value to the $this->request->data array, like this:
if($brand)
{
$this->request->data['Product']['brand_id'] = intval($brand['Brand']['id']);
}
else
{
$this->request->data['Brand']['name'] = $this->request->data['Product']['brand_name'];
}

CakePHP DB field update fail

I am using cakePHP why won't the name insert into the table, a null value seams to be passed as the table is updated but with out the name?
Table in Database
CREATE TABLE tests (
id serial not null unique primary key,
name varchar,
created timestamp default CURRENT_TIMESTAMP
)
add.ctp
<?php
echo $this->Form->create('Post');
echo $this->Form->input('name');
echo $this->Form->end('RSVP');
?>
Test Model
<?php
class Test extends AppModel {
var $name = 'Test';
}
TestContoller
<?php
class TestController extends AppController {
public $helpers = array('Html', 'Form');
var $name = "Test";
public function index() {
$this->set('tests', $this->Test->find('all'));
}
public function view($id = null) {
$this->Test->id = $id;
$this->set('Test', $this->Test->read());
}
public function add() {
if ($this->request->is('post')) {
if ($this->Test->save($this->request->data)) {
$this->Session->setFlash('Your post has been saved.');
$this->redirect(array('action' => 'index'));
}
else {
$this->Session->setFlash('Unable to add your post.');
}
}
}
public function edit($id = null) {
$this->Test->id = $id;
if ($this->request->is('get')) {
$this->request->data = $this->Post->read();
}
else {
if ($this->Test->save($this->request->data)) {
$this->Session->setFlash('Your post has been updated.');
$this->redirect(array('action' => 'index'));
}
else {
$this->Session->setFlash('Unable to update your post.');
}
}
}
public function delete($id) {
if ($this->request->is('get')) {
throw new MethodNotAllowedException();
}
if ($this->Test->delete($id)) {
$this->Session->setFlash('The post with id: ' . $id . ' has been deleted.');
$this->redirect(array('action' => 'index'));
}
}
}
In your method you missed to include $this->Test->create();, which will add new row to table and inset new data to it.
public function add() {
if ($this->request->is('post')) {
$this->Test->create(); // missed this line
if ($this->Test->save($this->request->data)) {
$this->Session->setFlash('Your post has been saved.');
$this->redirect(array('action' => 'index'));
}
else {
$this->Session->setFlash('Unable to add your post.');
}
}
}

Real-world testing of CakePHP controllers?

I'm writing a new application with CakePHP (just-released 1.2.4), using SimpleTest 1.0.1. I have read the relevant sections of the Cookbook, searched on the Bakery, and read Mark Story's postings on controller testing (the hard way and with mocks).
Unfortunately, none of this talks about real-world testing of non-trivial controllers. Lots of apps put areas of the site behind a login, yet I cannot figure out how to test the simple scenario of:
guest access to protected page redirects?
valid credentials sets expected session variables?
invalid credentials re-displays login page with error message?
The controller and test below do not work as I thought they would. Both assertions fail and I also get a PHP error:
FAILED
[NULL] should not be null at [.../app/tests/cases/controllers/users_controller.test.php line 79]
.../app/tests/cases/controllers/users_controller.test.php -> UsersControllerTest -> testLogin
FAILED
Equal expectation fails as [NULL] does not match [Integer: 1] at [.../app/tests/cases/controllers/users_controller.test.php line 80]
.../app/tests/cases/controllers/users_controller.test.php -> UsersControllerTest -> testLogin
ERROR
Unexpected PHP error [Undefined index: action] severity [E_NOTICE] in [.../cake/libs/controller/components/auth.php line 266]
.../app/tests/cases/controllers/users_controller.test.php -> UsersControllerTest -> testLogin
Here is the controller (baked plus Mark Story's "hard way" testing method):
class UsersController extends AppController
{
var $name = 'Users';
var $helpers = array('Html', 'Form');
var $components = array('Auth');
function login()
{
}
function logout()
{
$this->redirect($this->Auth->logout());
}
function index()
{
$this->set('users', $this->paginate());
}
function view($id = null)
{
if (!$id)
{
$this->Session->setFlash(__('Invalid User.', true));
$this->redirect(array('action'=>'index'));
}
$this->set('user', $this->User->read(null, $id));
}
function add()
{
if (!empty($this->data))
{
$this->User->create();
if ($this->User->save($this->data))
{
$this->Session->setFlash(__('The User has been saved', true));
$this->redirect(array('action'=>'index'));
}
else
{
$this->Session->setFlash(__('The User could not be saved. Please, try again.', true));
}
}
}
function edit($id = null)
{
if (!$id && empty($this->data))
{
$this->Session->setFlash(__('Invalid User', true));
$this->redirect(array('action'=>'index'));
}
if (!empty($this->data))
{
if ($this->User->save($this->data))
{
$this->Session->setFlash(__('The User has been saved', true));
$this->redirect(array('action'=>'index'));
}
else
{
$this->Session->setFlash(__('The User could not be saved. Please, try again.', true));
}
}
if (empty($this->data))
{
$this->data = $this->User->read(null, $id);
}
}
function delete($id = null)
{
if (!$id)
{
$this->Session->setFlash(__('Invalid id for User', true));
$this->redirect(array('action'=>'index'));
}
if ($this->User->del($id))
{
$this->Session->setFlash(__('User deleted', true));
$this->redirect(array('action'=>'index'));
}
}
}
Here is the test:
/* SVN FILE: $Id$ */
/* UsersController Test cases generated on: 2009-08-05 17:08:03 : 1249507923*/
App::import('Controller', 'Users');
class TestUsers extends UsersController
{
var $autoRender = false;
var $redirectUrl;
var $redirectStatus;
var $renderedAction;
var $renderedLayout;
var $renderedFile;
var $stopped;
function redirect($url, $status = null, $exit = true)
{
$this->redirectUrl = $url;
$this->redirectStatus = $status;
}
function render($action = null, $layout = null, $file = null)
{
$this->renderedAction = $action;
$this->renderedLayout = (is_null($layout) ? $this->layout : $layout);
$this->renderedFile = $file;
}
function _stop($status = 0)
{
$this->stopped = $status;
}
}
class UsersControllerTest extends CakeTestCase
{
var $fixtures = array('user');
var $Users = null;
function startTest()
{
$this->Users = new TestUsers();
$this->Users->constructClasses();
$this->Users->Component->initialize($this->Users);
}
function prepareForAction()
{
$this->Users->beforeFilter();
$this->Users->Component->startup($this->Users);
}
function endTest()
{
$this->Users->Session->destroy();
unset($this->Users);
ClassRegistry::flush();
}
//-----------------------------------------------------------------------
function testUsersControllerInstance()
{
$this->assertTrue(is_a($this->Users, 'UsersController'));
}
function testLogin()
{
$this->Users->data = array(
'User' => array(
'username' => 'admin',
'password' => 'admin'
)
);
$this->prepareForAction();
$this->Users->login();
$this->assertNotNull($this->Users->redirectUrl);
$this->assertEqual($this->Users->Session->read('Auth.User.id'), 1);
}
}
The test you have isn't really testing your UsersContoller, you're really testing the AuthComponent. If you want to do this you need to make sure you setup your TestUsersController the same as it would be in your app. In the case of your testLogin you need to set the controller's action and url:
function testLogin()
{
$this->Users->data = array(
'User' => array(
'username' => 'admin',
'password' => 'admin'
)
);
$this->Users->params['url']['url'] = '/users/login';
$this->Users->params['action'] = 'login';
$this->prepareForAction();
$this->Users->login();
$this->assertNotNull($this->Users->redirectUrl);
$this->assertEqual($this->Users->Session->read('Auth.User.id'), 1);
}
Alternately, I would suggest taking another look at Mark's mock objects post and using those methods to write tests for the controller code and mocking the auth component.

Categories