I would like to create a new model using another parameter
class Beacon extends AppModel {
/**
* Display field
*
* #var string
*/
public $displayField = 'name';
/**
* Validation rules
*
* #var array
*/
public $validate = array(
'UUID' => array(
'uuid' => array(
'rule' => array('uuid'),
),
),
);
//The Associations below have been created with all possible keys, those that are not needed can be removed
/**
* hasOne associations
*
* #var array
*/
public $hasOne = array(
'Position' => array(
'className' => 'Position',
'foreignKey' => 'beacon_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
}
I would like to ping this beacon passing in parameter the beacon UUID not the primary key.
class Ping extends AppModel {
//The Associations below have been created with all possible keys, those that are not needed can be removed
/**
* belongsTo associations
*
* #var array
*/
public $belongsTo = array(
'Beacon' => array(
'className' => 'Beacon',
'foreignKey' => 'beacon_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
}
How do I create a Ping object without the beacon primary_key but the UUID ?
on the ping controller I would like to add
public function pingBeaconWithUUID($uuid) {
How do I manage that ?
Thanks !
If the UUID is unique you can use it as value for the id field. The id needs not to be an integer although it is preferable.
But I would also propose to use the approach by AgRizzo and look up the id.
I do an app that show some products with price for register people.
When create the product page show me "Database Error"
"Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'Product.utype' in 'where clause'"
My ProductsController is like this:
class ProductsController extends AppController {
public function index() {
$this->Product->recursive = 0;
$products = $this->Product->find('all');
$this->set('products', $Product);
}
/**
* view method
*
* #throws NotFoundException
* #param string $id
* #return void
*/
public function view($id = null) {
$this->Product->id = $id;
if (!$this->Product->exists()) {
throw new NotFoundException(__('Invalid Product'));
}
$this->set('products', $this->Product->read(null, $id));
}
}
And the Model Product.php is like this:
class Product extends AppModel {
public $primaryKey = 'id_prod';
/**
* belongsTo associations
*
* #var array
*/
public $belongsTo = array(
'Occurrence' => array(
'className' => 'Occurrence',
'foreignKey' => 'occurrence_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
'User' => array(
'className' => 'User',
'foreignKey' => 'user_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
}
Can help me, please?
Thank you.
Per the very explicit error:
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column
'Product.utype' in 'where clause'"
Your code is looking for the colum 'utype' in the products table (which apparently doesn't exist). If you're not sure where your code is telling it to do that, just do a project-wide search for "utype" and update it to the correct field name.
I have the following models: Attachment and PurchaseOrder hence the datatables attachments and purchase_orders.
In PurchaseOrder, I have
class PurchaseOrder extends AppModel {
public $hasMany = array(
'Pdf' => array(
'className' => 'Attachment',
'foreignKey' => 'foreign_key',
'conditions' => array(
'Pdf.model' => 'PurchaseOrder'
)
),
'Zip' => array(
'className' => 'Attachment',
'foreignKey' => 'foreign_key',
'conditions' => array(
'Zip.model' => 'PurchaseOrder'
)
),
In Attachment, I have the following:
public $belongsTo = array(
'PurchaseOrder' => array(
'className' => 'PurchaseOrder',
'foreignKey' => 'foreign_key',
'counterCache' => array(
'attachment_count' => array('Pdf.model' => 'PurchaseOrder'),
)
),
My problem is when I try to use $this->PurchaseOrder->Zip->save($data); I run into problem because the alias Pdf is not found.
How do I overcome this while maintaining the countercache behavior of updating the attachment_count inside purchase_orders?
Note that if a PurchaseOrder is associated with 3 Pdf Attachments and 2 Zip Attachments, the attachment_count should read 3.
I am using cakephp 2.4.2
I stopped using counterCache and used afterSave instead.
/**
* Called after each successful save operation.
*
* #param boolean $created True if this save created a new record
* #param array $options Options passed from Model::save().
* #return void
* #link http://book.cakephp.org/2.0/en/models/callback-methods.html#aftersave
* #see Model::save()
*/
public function afterSave($created, $options = array()) {
// update the PurchaseOrder based on pdf
if (isset($this->data['Pdf'])) {
$this->updatePurchaseOrderAttachmentCount($this->data);
}
}
/**
*
* #param Array $data where we expect key Pdf
*/
public function updatePurchaseOrderAttachmentCount($data) {
// check for Pdf
$pdfSet = isset($data['Pdf']);
if (!$pdfSet) {
throw new Exception('we expect Pdf as a key in your $data');
}
// check for foreign_key and model
$pdfFKSet = isset($data['Pdf']['foreign_key']);
$pdfModelSet = isset($data['Pdf']['model']);
if (!$pdfFKSet || !$pdfModelSet) {
throw new Exception('we expect foreign_key and model as keys in your $data["Pdf"]');
}
$count = $this->find('count', array(
'conditions' => array(
'model' => 'PurchaseOrder',
'type' => 'application/pdf',
'foreign_key' => $data['Pdf']['foreign_key'],
)
));
if (!is_numeric($count)) {
throw new Exception('we expect numeric in the $count');
}
$poData = array(
'PurchaseOrder' => array(
'id' => $data['Pdf']['foreign_key'],
'attachment_count' => $count,
)
);
return $this->PurchaseOrder->save($poData);
}
I know this post is very old, but I recently faced a similar issue and found another way to handle the same problem. You can continue using the counterCache approach with multiple counterCache, the only difference would be, you need to add you association on the fly, in the __construct method of your model.
public function __construct($id = false, $table = null, $ds = null) {
parent::__construct($id, $table, $ds);
/**
* When using Aliases, associations need to be added on the fly, otherwise, the CounterScope conditions would result in an SQL Error, during counterCache updates
*/
$this->bindModel(
array('belongsTo' => array(
'PurchaseOrder' => array(
'className' => 'PurchaseOrder',
'foreignKey' => 'foreign_key',
'counterCache' => array(
'attachment_count' => array($this->alias . '.model' => 'PurchaseOrder'),
'attachment_count' => array($this->alias . '.model' => 'PurchaseOrder')
)
)
)
)
);
}
Why won't my user and coupon objects get saved to the database when a new record is created?
I am using typo3 v 4.5.30 and making a little extension (my first) to manage some coupons. When I create a coupon I save the creator (a frontenduser) and it gets saved to the DB correctly. But when I do the same thing for a coupon user that user ( and the coupon ) do not get saved to the db. Consider this code frag which attempts to save the user and the coupon in a usedcoupon table. The usedcoupon table basically just has 2 columns one for the user and one for the coupon.
To get a usedcoupon object I called the objectmanagers create method. The user and coupon objects I already have and look right when I var_dump them. Even when I get them from the usedcoupon object they look ok but they don't get saved to the db even when the new record gets created. This code in in my CouponController in an action method.
$used = $this->objectManager>create('Tx_BpsCoupons_Domain_Model_UsedCoupon');
$used->setCoupon($coupon);
$used->setUser($user);
$used->setGuest("myemail#ddd.com");
$userx = $used->getUser();
$coupx = $used->getCoupon();
/// var_dumps of userx and coupx show good objects
$this->usedCouponRepository->add($used);
//after this I can examine the db and see the new record but the user and coupon fields are empty, and no errors are seen
Thanks
PS here is my TCA from Usedcoupon.php
<?php
if (!defined ('TYPO3_MODE')) {
die ('Access denied.');
}
$TCA['tx_bpscoupon_domain_model_usedcoupon'] = array(
'ctrl' => $TCA['tx_bpscoupon_domain_model_usedcoupon']['ctrl'],
'interface' => array(
'showRecordFieldList' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, user, coupon, guest',
),
'types' => array(
'1' => array('showitem' => 'sys_language_uid;;;;1-1-1, l10n_parent, l10n_diffsource, hidden;;1, user, coupon, guest,--div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access,starttime, endtime'),
),
'palettes' => array(
'1' => array('showitem' => ''),
),
'columns' => array(
'sys_language_uid' => array(
'exclude' => 1,
'label' => 'LLL:EXT:lang/locallang_general.xml:LGL.language',
'config' => array(
'type' => 'select',
'foreign_table' => 'sys_language',
'foreign_table_where' => 'ORDER BY sys_language.title',
'items' => array(
array('LLL:EXT:lang/locallang_general.xml:LGL.allLanguages', -1),
array('LLL:EXT:lang/locallang_general.xml:LGL.default_value', 0)
),
),
),
'l10n_parent' => array(
'displayCond' => 'FIELD:sys_language_uid:>:0',
'exclude' => 1,
'label' => 'LLL:EXT:lang/locallang_general.xml:LGL.l18n_parent',
'config' => array(
'type' => 'select',
'items' => array(
array('', 0),
),
'foreign_table' => 'tx_bpscoupon_domain_model_usedcoupon',
'foreign_table_where' => 'AND tx_bpscoupon_domain_model_usedcoupon.pid=###CURRENT_PID### AND tx_bpscoupon_domain_model_usedcoupon.sys_language_uid IN (-1,0)',
),
),
'l10n_diffsource' => array(
'config' => array(
'type' => 'passthrough',
),
),
't3ver_label' => array(
'label' => 'LLL:EXT:lang/locallang_general.xml:LGL.versionLabel',
'config' => array(
'type' => 'input',
'size' => 30,
'max' => 255,
)
),
'hidden' => array(
'exclude' => 1,
'label' => 'LLL:EXT:lang/locallang_general.xml:LGL.hidden',
'config' => array(
'type' => 'check',
),
),
'starttime' => array(
'exclude' => 1,
'l10n_mode' => 'mergeIfNotBlank',
'label' => 'LLL:EXT:lang/locallang_general.xml:LGL.starttime',
'config' => array(
'type' => 'input',
'size' => 13,
'max' => 20,
'eval' => 'datetime',
'checkbox' => 0,
'default' => 0,
'range' => array(
'lower' => mktime(0, 0, 0, date('m'), date('d'), date('Y'))
),
),
),
'endtime' => array(
'exclude' => 1,
'l10n_mode' => 'mergeIfNotBlank',
'label' => 'LLL:EXT:lang/locallang_general.xml:LGL.endtime',
'config' => array(
'type' => 'input',
'size' => 13,
'max' => 20,
'eval' => 'datetime',
'checkbox' => 0,
'default' => 0,
'range' => array(
'lower' => mktime(0, 0, 0, date('m'), date('d'), date('Y'))
),
),
),
'user' => array(
'exclude' => 0,
'label' => 'LLL:EXT:bpscoupon/Resources/Private/Language/locallang_db.xml:tx_bpscoupon_domain_model_usedcoupon.user',
'config' => array(
'type' => 'select',
'foreign_table' => 'fe_users'
),
),
'coupon' => array(
'exclude' => 0,
'label' => 'LLL:EXT:bpscoupon/Resources/Private/Language/locallang_db.xml:tx_bpscoupon_domain_model_usedcoupon.coupon',
'config' => array(
'type' => 'select',
'foreign_table' => 'tx_bpscoupons_domain_model_coupon'
),
),
'guest' => array(
'exclude' => 0,
'label' => 'LLL:EXT:bpscoupon/Resources/Private/Language/locallang_db.xml:tx_bpscoupon_domain_model_usedcoupon.guest',
'config' => array(
'type' => 'input',
'size' => 30,
'eval' => 'trim'
),
),
),
);
?>
PPS adding usedcoupon model code:
<?php
/***************************************************************
* Copyright notice
*
* (c) 2013 Cory Taylor <cory#bigplayersystems.com>, Big Player Systems
*
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
/**
*
*
* #package bps_coupons
* #license http://www.gnu.org/licenses/gpl.html GNU General Public License, version 3 or later
*
*/
class Tx_BpsCoupons_Domain_Model_UsedCoupon extends Tx_Extbase_DomainObject_AbstractEntity {
/**
* Used By
*
* #var Tx_BpsCoupons_Domain_Model_FrontendUser
*/
protected $user;
/**
* Returns the $user
*
* #return Tx_BpsCoupons_Domain_Model_FrontendUser $user
*/
public function getUser() {
echo "<br/>" . __FUNCTION__ . __LINE__ . " <br/>";
return $this->user;
}
/**
* Sets the $user
*
* #param #param Tx_BpsCoupons_Domain_Model_FrontendUser $user
* #return void
*/
public function setUser(Tx_BpsCoupons_Domain_Model_FrontendUser $user) {
$this->user = $user;
}
/**
* the used coupon
*
* #var Tx_BpsCoupons_Domain_Model_Coupon
*/
protected $coupon;
/**
* Returns the $coupon
*
* #return Tx_BpsCoupons_Domain_Model_Coupon $coupon
*/
public function getCoupon() {
return $this->coupon;
}
/**
* Sets the $coupon
*
* #param #param Tx_BpsCoupons_Domain_Model_Coupon $coupon
* #return void
*/
public function setCoupon(Tx_BpsCoupons_Domain_Model_Coupon $coupon) {
$this->coupon = $coupon;
}
/**
* the guest email
*
* #var string
*/
protected $guest;
/**
* Returns the $guest
*
* #return string $guest
*/
public function getGuest() {
return $this->guest;
}
/**
* Sets the $guest email
*
* #param string $guest
* #return void
*/
public function setGuest( $guest) {
$this->guest = $guest;
}
}
?>
PPPS: I tried adding a basic text field for email addresses but it turns out they don't get saved either. I had thought the issue was that the user and coupon filed were references to rows in other tables but now it turns out that simpler things do not get saved either.
PP PP S: may as well look into my ext_tables file too:
<?php
if (!defined('TYPO3_MODE')) {
die ('Access denied.');
}
Tx_Extbase_Utility_Extension::registerPlugin(
$_EXTKEY,
'Bpscoupons',
'BPS_Coupons'
);
t3lib_extMgm::addStaticFile($_EXTKEY, 'Configuration/TypoScript', 'BPS_Coupons');
t3lib_extMgm::addLLrefForTCAdescr('tx_bpscoupons_domain_model_coupon', 'EXT:bps_coupons/Resources/Private/Language/locallang_csh_tx_bpscoupons_domain_model_coupon.xml');
t3lib_extMgm::allowTableOnStandardPages('tx_bpscoupons_domain_model_coupon');
$TCA['tx_bpscoupons_domain_model_coupon'] = array(
'ctrl' => array(
'title' => 'LLL:EXT:bps_coupons/Resources/Private/Language/locallang_db.xml:tx_bpscoupons_domain_model_coupon',
'label' => 'name',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
'dividers2tabs' => TRUE,
'sortby' => 'sorting',
'versioningWS' => 2,
'versioning_followPages' => TRUE,
'origUid' => 't3_origuid',
'languageField' => 'sys_language_uid',
'transOrigPointerField' => 'l10n_parent',
'transOrigDiffSourceField' => 'l10n_diffsource',
'delete' => 'deleted',
'enablecolumns' => array(
'disabled' => 'hidden',
'starttime' => 'starttime',
'endtime' => 'endtime',
),
'searchFields' => 'name,description,expiry,hall,date_created,creator,barcode,',
'dynamicConfigFile' => t3lib_extMgm::extPath($_EXTKEY) . 'Configuration/TCA/Coupon.php',
'iconfile' => t3lib_extMgm::extRelPath($_EXTKEY) . 'Resources/Public/Icons/tx_bpscoupons_domain_model_coupon.gif'
),
);
t3lib_extMgm::addLLrefForTCAdescr('tx_bpscoupons_domain_model_usedcoupon', 'EXT:bpscoupons/Resources/Private/Language/locallang_csh_tx_bpscoupons_domain_model_usedcoupon.xml');
t3lib_extMgm::allowTableOnStandardPages('tx_bpscoupons_domain_model_usedcoupon');
$TCA['tx_bpscoupons_domain_model_usedcoupon'] = array(
'ctrl' => array(
'title' => 'LLL:EXT:bpscoupons/Resources/Private/Language/locallang_db.xml:tx_bpscoupons_domain_model_usedcoupon',
'label' => 'user',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
'dividers2tabs' => TRUE,
'versioningWS' => 2,
'versioning_followPages' => TRUE,
'origUid' => 't3_origuid',
'languageField' => 'sys_language_uid',
'transOrigPointerField' => 'l10n_parent',
'transOrigDiffSourceField' => 'l10n_diffsource',
'delete' => 'deleted',
'enablecolumns' => array(
'disabled' => 'hidden',
'starttime' => 'starttime',
'endtime' => 'endtime',
),
'searchFields' => 'user,coupon,guest,',
'dynamicConfigFile' => t3lib_extMgm::extPath($_EXTKEY) . 'Configuration/TCA/Usedcoupon.php',
'iconfile' => t3lib_extMgm::extRelPath($_EXTKEY) . 'Resources/Public/Icons/tx_bpscoupons_domain_model_usedcoupon.gif'
),
);
?>
If that happens, most probably your objects are not persisted. Normally Extbase persists changes to objects after the end of a request. But if you e.g. return your response as JSON and then exit your action, the persistenceManager is not called.
You can persist manually by injecting the persistenceManager to your controller:
/**
* #var Tx_Extbase_Persistence_Manager
*/
protected $persistenceManager;
/**
* #param Tx_Extbase_Persistence_Manager $persistanceManager
* #return void
*/
public function injectPersistenceManager(Tx_Extbase_Persistence_Manager $persistenceManager) {
$this->persistenceManager = $persistenceManager;
}
and then call it after you added the new object:
$persistenceManager->persistAll();
In TYPO3 4.7+, you can use the #inject annotation in the doc comment of $persistenceManager to inject the persistenceManager and don't need the inject function.
If this doesn't solve the problem, maybe there's a problem with your TCA.
We are converting an application for use with CakePHP 2.0.3.
For some reason, I cannot seem to set proper relations between my models.
Here's an example:
User (id, petid, country, picid, ...)
Pet (id, userid, picid, ...)
Picture (id, albumid, ....)
Album (id, userid, petid, ...)
The meanings of these are the following:
- A user can have multiple pets, but can only have selected one pet at the same time (therefore, petid in User)
- Pets belong to one user
- Pets and Users can have multiple pictures, but only one profile picture, therefore Pet.picid and User.picid
- Pets and users can have multiple Albums
I set up my models in CakePHP, but I cannot figure out which relations to use between them since the Database is not following the conventions.
I've tried the following:
User
-> hasMany(Pets)
-> hasOne(Picture)
-> hasMany(Album)
Pet
-> belongsTo(User) (works fine, with foreignkey userid)
-> hasMany(Album)
-> hasOne(Picture)
Album
-> hasMany(Picture)
---- Logic to achieve this? It either belongs to a user or pet-----
-> belongsTo(User)
-> belongsTo(Pet)
Picture
-> belongsTo(Album)
I'm new to CakePHP and cannot figure out the way to go here.
Do you have any suggestions?
I would suggest using Aliases in your relationships which will help get your head around the data being returned.
For example, your User model could use SelectedPet and ProfilePicture in it's associations:
User.php model
/**
* belongsTo associations
*
* #var array
*/
public $belongsTo = array(
'SelectedPet' => array(
'className' => 'Pet',
'foreignKey' => 'petid'
),
'ProfilePicture' => array(
'className' => 'Picture',
'foreignKey' => 'picid',
)
);
/**
* hasMany associations
*
* #var array
*/
public $hasMany = array(
'Album' => array(
'className' => 'Album',
'foreignKey' => 'userid',
'dependent' => false
),
'Pet' => array(
'className' => 'Pet',
'foreignKey' => 'userid',
'dependent' => false
)
);
Your Pet model could use ProfilePicture as well:
/**
* belongsTo associations
*
* #var array
*/
public $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'userid'
),
'ProfilePicture' => array(
'className' => 'Picture',
'foreignKey' => 'picid'
)
);
/**
* hasMany associations
*
* #var array
*/
public $hasMany = array(
'Album' => array(
'className' => 'Album',
'foreignKey' => 'petid',
'dependent' => false
)
);
Picture model:
/**
* belongsTo associations
*
* #var array
*/
public $belongsTo = array(
'Album' => array(
'className' => 'Album',
'foreignKey' => 'albumid'
)
);
..and finally your Album model:
/**
* belongsTo associations
*
* #var array
*/
public $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'userid'
),
'Pet' => array(
'className' => 'Pet',
'foreignKey' => 'petid'
)
);
/**
* hasMany associations
*
* #var array
*/
public $hasMany = array(
'Picture' => array(
'className' => 'Picture',
'foreignKey' => 'albumid',
'dependent' => false
)
);
With regards to the logic of an Album belonging to a User or a Pet, you could just handle this in your controller when saving data or returning it. I.e User is given preference over Pet.
I hope this helps.