CakePHP having trouble saving data (HABTM) - php

I am trying to create wish lists.
There are user and product models. A user has a wish list. A wish list has many products.
The reason I am making it user has wishlist and wishlist has products is so I can have a url like wish_lists/add/:product_id
I created a table called wish_lists with id, user_id, and name.
I also created a table called products_wish_lists with wish_list_id and product_id.
I made here is the wishlists controller:
class WishListsController extends AppController
{
var $hasOne = 'User';
var $hasMany = 'Product';
function beforeFilter()
{
parent::beforeFilter();
$this->Auth->deny('add');
}
function add($id)
{
$user = $this->Session->read("Auth.User");
$this->WishList->set(array(
'User.id' => $user['id'],
'Product.id'=>$id,
'WishList.name'=>'default'
));
if($this->WishList->save())
{
$this->Session->setFlash('This product has been added to your wishlist.', 'flash_good');
}
else
{
$this->Session->setFlash('Error: This product was not added to your wishlist.', 'flash_bad');
}
$this->redirect(array("controller"=>"products","action"=>"view",$id));
}
}
When I go to localhost/wish_lists/add/1 It tells me everytime that it saved. but no data is being added to the database.
Not sure what I am doing wrong?

I never do it that way, I always build a $data array to pass as parameter one to the save function.
I'm not sure, therefore, whether that syntax will allow you to specify the model as you have done, i.e. 'Model.field'. In any case, $this->WishList->save() will only save the Wishlist part.
Better, in my opinion, would be:
$saveData = array(
'User'=>array('id'=>$user['id']),
'Product'=>array('id'=>$id),
'WishList'=>array('name'=>'default'));
$this->WishList->saveAll($saveData);
(or something like that, I've been programming ColdFusion for the last three months and my PHP can be a bit addled)

you are setting the array wrong. it should be $data['User']['id'] = 123; $data['Product']['id'] = 321;
$this->Wishlist->saveAll($data);
There is no point saving the name as that can be found from the product table.
you can have a look at the code here for more ideas https://github.com/Infinitas-Plugins/shop
there is a generic component method in the following link that saves products to the cart or wishlist (different db's) as its pretty much the same thing.
https://github.com/Infinitas-Plugins/shop/blob/master/controllers/components/shop.php#L62

Related

Calling function with return value in cakephp

I am new to cakephp. I have a problem with calling the function. here is my issue.
In Contrloller file i get all the values using the following function
public function index()
{
$conditions = array(
'order' => array('Histroy.chat_sk DESC')
);
$this->set('histroys', $this->Histroy->find('all',$conditions));
}
In My model file have the following,
class Histroy extends AppModel
{
public $tablePrefix = 'plc_';
public $useTable = 'chat_history';
}
In my view file i have listed the values using foreach() function and that as follows
foreach ($histroys as $histroy):
$oper_name = $histroy['Histroy']['operator_fk'];
$operator_email = $histroy['Histroy']['email'];
endforeach
in that opertaor_fk is a field in history table. So i need get the operator name by another table as operators. So i need to call that function in the view.
Ex : In core we can do like as,
$operator_name = operator_name($fetch['operator_id']);
Function should be like this:
function operator_name($id)
{
// Select the value for the matched field in the operator
return $operator_name;
}
In cakephp how can i retrieve the values.
Please help me out to fix this. Thanks in Advance
Follow the blog tutorial for cake. It'll explain how to create associations and relationships between tables to let you do what is is you want, but in a nutshell, you need to create a relationship between History and Operator models and work from there.

Magento Controller shows all the rows from table

As I am required to pirnt the ratings of products in JSON format, i have made a module with controller and rating.php file in model folder. We I run the controller it shows all the data from that table, But I required only a single row. So through the url i am passing a parameter, but it wont works. I am attaching my indexcontroller.php here. suggest me upon this.
<?php
class Modulename_CustomRating_IndexController extends Mage_Core_Controller_Front_Action
{
public function indexAction ()
{
$arrParams = $this->getRequest()->getParams();
var_dump($arrParams);
$collection = Mage::getModel('Modulename_CustomRating_Model_CustomRating')->getCollection();
}
print_r (json_encode($collection ->getData()));
}
}
?>
As I am passing url as:localhost/magento/customrating?vote_id=1 , it is taking the parameter to it but returns whole table's data. I know this is due to getData(); but how to make to get the required row?
You have to use setEntityPkFilter method. Check Mage_Rating_Model_Resource_Rating_Option_Vote_Collection class for other methods.
$product_id = $this->getRequest()->getParam('product_id'); // or 'vote_id'
$collection = Mage::getModel('Modulename_CustomRating_Model_CustomRating')
->getResourceCollection()
->setEntityPkFilter($product_id);
If you want only 1 column you can try some Zend stuff because you can't use addAttributeToSelect. getSelect() returns Zend like query:
$adapter = $this->getConnection(); // $this->getConnection();
$collection->getSelect()
->reset(Zend_Db_Select::COLUMNS) // remove all columns
->columns('attribute_name'); // add only needed one
$result = $adapter->fetchAll($select);
Not sure whether this would work. It's not tested, just an idea.

CakePHP searchable tags

I have made an online shop for clothes and probably I need to make some tagging system.
The whole application is build on CakePHP and I need an idea for managing all the products, something similar to ebay.
For example to tag each product with it's price , type, producer, size , status
And for example some of them should be multi-searchable, to be able to search for an item with: price between $10 and $20, with size S or M
Have an attributes table that will basically act as a key/value storage and assign these attributes to each product.
Attributes itself could have an attribute_options table from where you can read the different available sizes for an attribute.
You'll then just have to search the attributes table and product table.
From what you describe, you shouldn't need any additional tables. Just add them as fields in the product table, and query based on that. It will be faster, more logically laid out...etc.
Your example would be searchable like below. (It seems a bit overkill, but will make any future finds really simple, and follows the fat controller, skinny model mantra:
//ProductsController
public function whatever() {
$opts = array(
'price_high' => 10,
'price_low' => 20,
'sizes' => array('S', 'M')
);
$this->Product->getProducts($opts);
}
//Product Model
public function getProduts($opts = null) {
//initialize variables
$params = array('conditions'=>array());
//size(s)
if(!empty($opts['sizes']) {
array_push($params['conditions'], array('Product.size'=>$opts['sizes']));
}
//price(s)
if(!empty($opts['price_high']) {
array_push($params['conditions'], array('Product.price <='=>$opts['price_high']));
}
if(!empty($opts['price_low']) {
array_push($params['conditions'], array('Product.price >='=>$opts['price_low']));
}
return $this->find('all', $params);
}

Manage groups in different page with sfDoctrineGuardPlugin

i'm using sfDoctrineGuardPlugin, but i would like a little change, i have 2 groups(admins,users) and i want to manage them separately, what i mean is a page that only shows me the "admins" group and another one the "users" group, i want this because users in "users" group will have some additional info and behavior, i already create a "sfGuardUser" empty module in my backend app, so i can overwrite and add everything i want, i create de actions.class.php
class sfGuardUserActions extends autoSfGuardUserActions
{
public function executeAdmins(sfWebRequest $request)
{
// sorting
if ($request->getParameter('sort') && $this->isValidSortColumn($request->getParameter('sort')))
{
$this->setSort(array($request->getParameter('sort'), $request->getParameter('sort_type')));
}
// pager
if ($request->getParameter('page'))
{
$this->setPage($request->getParameter('page'));
}
$this->pager = $this->getPager();
$this->sort = $this->getSort();
}
}
i copied exactly the "executeIndex" function from "autoSfGuardUserActions" class in cache, and now i can go to guard/admin and it acts like the default one, but now, how can i show only de users from "admins" group?
You have to modify buildQuery() method.

MVC model where to put data specific checks

I'm writing my first application with Zendframework.
My question is about the Model–View–Controller (MVC) architectural pattern.
I currently have a model with refer to a database table.
Here's the classes that I currently have :
Model_Person
Model_PersonMapper
Model_DbTable_Person
Now, I see a lot of examples on the net, but all of them are simple cases of insert/update/delete.
In my situation, I have to check if a person exists, and if it doesn't, I have to insert it and retrieve the ID (I know save return the Id, but it's not exactly what I have to do, this is and example).
It's quit simple, but I want to know where to put the database logic for all the others specific cases. Some others cases might involve checks across other tables or ... whatever !
Should I add all the specific functions in my Model_XXXXMapper with something that would be very specific with the current validation/process that I want to do? like a function getIdOfThePersonByNameOrInsertIfNotExists() (sample name of course!!!)
Or should it reside in the controller with some less specifics access to my model would be validated?
In other word, where do I put all the data specifics functions or check ?
I think the real work should occur in your model objects, not in the controller. Any selects/creates that start with the person table would be in the DbTable_Person object, things like:
// DbTable_Person
// returns sets of or single Person objects
public function createByName( $name ) // perhaps throws exception if name already exists
public function findById( $id )
public function findByName( $name )
public function findHavingAccount( $account_id ) // references another table
// controller
// with your example, like what Galen said,
// I would let the controller handle this logic
$person = $person_table->findByName($name);
if ( !$person ) {
$person = $person_table->createByName($name);
}
if ( !$person ) { throw new Zend_Exception('huh?'); }
$id = $person->id; // you wanted the ID
I would definitely split the function up into search/create functions.
Here's a basic implementation...
$personTG = new Model_PersonTableGateway;
if ( !$person = $personTG->findByName( $name ) ) {
$person = new Model_Person;
$person->name = $name;
// other variables
$newPersonId = $personTG->create( $person ); // creates a new person
}
I use table gateway. You can substitute your class for the TG.
You can have the create() function return just the id of the newly created person, or the entire person...it's up to you.
You might be interested in Zend_Validate_Db_NoRecordExists and its sister. If you are using Zend_Form you can add this validator to your form element. Many folks use Zend_Form to validate and filter data before they reach the domain model.
If you are not using Zend_Form, you can simply use this validation class in your service layer. A simple service class could be something like
`
class Service_Person_Validate
{
public function creatable($data)
{ // return true|false
}
}

Categories