I have a table called products. In product table I have 2 fields created_at and update_at. I don't want to change it to created and modified.
Without change table fields name, how can I assign that created_at field is created to get cakephp time helper auto update date ?
My entity I have tried below
protected $_accessible = [
'created_at' => $this->created,
'updated_at' => $this->modified,
];
Getting error.
Read the manual. https://book.cakephp.org/4/en/orm/behaviors/timestamp.html#basic-usage
If you need to modify fields with different names, or want to update additional timestamp fields on custom events you can use some additional configuration:
class OrdersTable extends Table
{
public function initialize(array $config): void
{
$this->addBehavior('Timestamp', [
'events' => [
'Model.beforeSave' => [
'created_at' => 'new',
'updated_at' => 'always',
],
'Orders.completed' => [
'completed_at' => 'always'
]
]
]);
}
}
Related
I have three tables:
user
game
user_game
game.user_id - user which CREATE game. Table user_game describes users that ADDED games not create, it
has user_id and game_id fields. I have GameSearch Model which should search current user ADDED games. Here The search method;
public function search($params)
{
// HERE I SHOULD GET ONLY GAMES WHICH ADDED BY USER via table user_game
$query = Game::find();
$dataProvider = new ActiveDataProvider([
'query' => $query,
'sort' => [
'defaultOrder' => [
'sorting' => SORT_DESC,
]
],
]);
if (!empty($params['pageSize'])) {
$dataProvider->pagination->pageSize = $params['pageSize'];
}
$this->load($params);
if (!$this->validate()) {
// uncomment the following line if you do not want to return any records when validation fails
// $query->where('0=1');
return $dataProvider;
}
// grid filtering conditions
$query->andFilterWhere([
'id' => $this->id,
'user_id' => $this->user_id,
'visible' => $this->visible,
'sorting' => $this->sorting,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
]);
$query->andFilterWhere(['like', 'name', $this->name])
->andFilterWhere(['like', 'slug', $this->slug])
->andFilterWhere(['like', 'image', $this->image])
->andFilterWhere(['like', 'description', $this->description])
->andFilterWhere(['>=', 'created_at', $this->date_from ? $this->date_from : null])
->andFilterWhere(['<=', 'created_at', $this->date_to ? $this->date_to : null])
->andFilterWhere(['>=', 'updated_at', $this->date_upd_from ? $this->date_upd_from : null])
->andFilterWhere(['<=', 'updated_at', $this->date_upd_to ? $this->date_upd_to : null]);
return $dataProvider;
}
So i need get games list via table user_game where user_id = current Id user, game_id = game id. Please help.
first of all you need two relation in first in Game model which will fetch one to many data from user_game table (model), then in model user_game you need write a relation to get user from user table (model)
$query->joinWith(['userGame', 'userGame.user']);
->andFilterWhere(['=', 'tbl_user.id', Yii::app()->user->id])
I have defined in an entity this :
protected $_virtual = [ 'full_name' ];
protected function _getFullName()
{
return( $this->_properties['firstname'] . ' ' . $this->_properties['lastname'] );
}
But the full_name field is not retrieved by any query ( paginator or find('all') ) ... when the table is referred as an associated table.
The main table is GenPersons.
In that case, the field is showed correctly.
But then the I make
$this->paginate = [ 'contain' => ['GenPersons'] ]
from the AerPilots controller ( AerPilots is a model ) ; and try to get the field as
$aerPilot->gen_person->full_name;
nothing is showed.
Am I forgetting something ?
I found it.
The problem was in the association on the model.
The GenPersons table belongs to General plugin.
The AerPilots table belongs to Aeronautical plugin.
When I baked the model for AerPilots, it generated this code :
$this->belongsTo('GenPersons', [
'foreignKey' => 'gen_person_id',
'className' => '**Aeronautical**.GenPersons'
]);
And it must be :
$this->belongsTo('GenPersons', [
'foreignKey' => 'gen_person_id',
'className' => '**General**.GenPersons'
]);
I am using Cakephp 3.2.10
I am able to load associated data with hasOne association and hasMany association. However, I have one hasOne inside the table associated with hasMany, and that gives error.
I have following tables
companies
company_revenues
currencies
states
countries.
CompaniesTable class has hasOne associations with states,countries and it works. CompaniesTable has hasMany association with CompanyRevenuesTable, and it works. CompanyRevenues table has a hasOne association with currencies, this gives error.
My relevant Code :
CompaniesTable.php
<?php
namespace Admin\Model\Table;
use Cake\ORM\Table;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
class CompaniesTable extends Table
{
public function initialize(array $config)
{
$this->primaryKey('company_id');
$this->addAssociations(
[
'hasOne' =>
[
'Countries' =>
[ 'className' => 'Countries','foreignKey' => 'id','bindingKey' => 'company_country_id' ]
,'States' =>
[ 'className' => 'States','foreignKey' => 'id','bindingKey' => 'company_state_id' ]
,'Sectors' =>
[ 'className' => 'Sectors','foreignKey' => 'id','bindingKey' => 'company_sector_id' ]
]
,'hasMany' =>
[
'CompanyRevenues' =>
[ 'className' => 'CompanyRevenues','foreignKey' => 'revenue_company_id','bindingKey' => 'company_id' ]
]
]);
}
public function buildRules(RulesChecker $rules)
{
$rules->add( $rules->isUnique(['company_name']) );
return $rules;
}
public function compsTotalCount( Query $query )
{
$result = $query->select(['companiesCount' => $query->func()->count('*')])->first();
return $result;
}
public function findPopular( Query $query )
{
$result = $query->where(['times_viewed >' => 10]);
// debug($result);
return $result;
}
}
?>
CompanyRevenuesTable.php
<?php
namespace Admin\Model\Table;
use Cake\ORM\Table;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
class CompanyRevenuesTable extends Table
{
public function initialize(array $config)
{
$this->table('company_revenues');
$this->addAssociations(
[
'hasOne' =>
[
'Currencies' =>
[ 'className' => 'Currencies','foreignKey' => 'id','bindingKey' => 'revenue_currency_id' ]
]
]);
}
}
?>
My CompaniesController.php
profile action
public function profile( $id = null )
{
$company = $this->Companies->find()
->where(['company_id' => $id])
->contain(['CompanyRevenues'])->first();
if( ! $this->request->is('ajax') )
{
$companyRevenuesTable = TableRegistry::get('CompanyRevenues');
$companyRevenues = $companyRevenuesTable->find()
->where(['revenue_company_id' => $company->company_id])
->contain(['Currencies']);
debug($companyRevenues);
}
if( $this->request->is('ajax') )
{
$company = $this->Companies->patchEntity($company, $this->request->data);
$company->company_last_updated = date("Y-m-d H:i:s");
$ajaxRespArr = array();
if( $this->Companies->save($company) )
{
$ajaxRespArr["result"] = 1;
}
else
{
$ajaxRespArr["result"] = 0;
}
$this->set( 'ajaxRespArr',$ajaxRespArr );
$this->set('_serialize', ['ajaxRespArr']);
}
else
{
$this->set('company', $company);
}
}
The debug on $$companyRevenues
gives error
\plugins\Admin\src\Controller\CompaniesController.php (line 92)
object(Cake\ORM\Query) {
(unable to export object: CompanyRevenues is not associated with Currencies)
}
I think the error is because of _ in my table company_revenues.
Can any one guide me please ?
Actually, in the profiles action, i do not want to load company revenues separately, as they come along with company.
I tried the following originally :
$company = $this->Companies->find()
->where(['company_id' => $id])
->contain(
[
'CompanyRevenues' => ["Currencies"]
])->first();
But that give error :
CompanyRevenues is not associated with Currencies InvalidArgumentException
Could this be caused by using Auto-Tables?
Some of the Table objects in your application were created by instantiating "Cake\ORM\Table" instead of any other specific subclass.
This could be the cause for this exception. Auto-Tables are created for you under the following circumstances:
The class for the specified table does not exist.
The Table was created with a typo: TableRegistry::get('Atricles');
The class file has a typo in the name or incorrect namespace: class Atricles extends Table
The file containing the class has a typo or incorrect casing: Atricles.php
The Table was used using associations but the association has a typo: $this->belongsTo('Atricles')
The table class resides in a Plugin but no plugin notation was used in the association definition.
Please try correcting the issue for the following table aliases:
CompanyRevenues
I would suggest adding the reverse relationships as well and see what happens.
By reverse relationships I mean belongsTo in your currencies and companyRevenues classes.
Currencies belongTo companyRevenues and
CompanyRevenues belongTo company class.
See what your debugging provides.
I want to save a bunch of static records in my database with a given uuid, this is for testing purposes, so that on every system the application starts with the exact same dataset.
When inserting with SQL this is no problem but I wanted to use the CakePHP way ( I use a migrations file for this, but that does not matter).
The problem is that I give cake a data array like this and save it:
$data = [
['id' => '5cedf79a-e4b9-f235-3d4d-9fbeef41c7e8', 'name' => 'test'],
['id' => 'c2bf879c-072c-51a4-83d8-edbf2d97e07e', 'name' => 'test2']
];
$table = TableRegistry::get('My_Model');
$entities = $table->newEntities($data, [
'accessibleFields' => ['*' => true],
'validate' => false
]);
array_map([$table, 'save'], $entities );
Everything saves, but all my items have been given a different uuid, If I debug a record after saving it shows the original uuid in the entity
'new' => false,
'accessible' => [
'*' => true
],
'properties' => [
'id' => '6b4524a8-4698-4297-84e5-5160f42f663b',
'name' => 'test',
],
'dirty' => [],
'original' => [
'id' => '5cedf79a-e4b9-f235-3d4d-9fbeef41c7e8'
],
So why does cake generate a new uuid for me? and how do I prevent it
This doesn't work because primary keys are unconditionally being generated before the insert operation, see
https://github.com/cakephp/cakephp/blob/3.0.0/src/ORM/Table.php#L1486-L1490
// ...
$id = (array)$this->_newId($primary) + $keys;
$primary = array_combine($primary, $id);
$filteredKeys = array_filter($primary, 'strlen');
$data = $filteredKeys + $data;
// ...
$statement = $this->query()->insert(array_keys($data))
->values($data)
->execute();
// ...
Currently the UUID type is the only type that implements generating IDs, so providing custom IDs works with other types.
You can workaround this by for example overriding the _newId() method in your table so that it returns null, which effectively results in the existing primary key not being overwritten.
protected function _newId($primary)
{
// maybe add some conditional logic here
// in case you don't want to be required
// to always manually provide a primary
// key for your insert operations
return null;
}
I'm trying to Update/Save TradingPartner Entities (Customers and Suppliers) that can have many Addresses associated (TradingPartnerAddresses).
I have an array of changed TradingPartners and i'm using Cake's patchEntities() function to merge the existing records with the modified ones.
The issue is that Cake is incorrectly marking the associated addresses as dirty and when looping through the Entities to save them it's trying to re-insert the existing addresses - causing duplicate addresses.
Here's the code:
Trading Partners Controller
//Load the trading partners model
$tradingPartners = TableRegistry::get('TradingPartners');
//find all existing trading partners and their associated addresses
$currentTradingPartners = $tradingPartners->find('all')
->contain(['TradingPartnerAddresses']);
//Patch trading partner changes
//Cake automagically handles 1 level of associations
$patchedTpEntities = $tradingPartners->patchEntities($currentTradingPartners, $partners);
//loop through and save all dirty fields
foreach ($patchedTpEntities as $tpEntity) {
if ($tradingPartners->save($tpEntity)) {
} else {
//TODO
}
}
Trading Partners Table
public function initialize(array $config) {
$this->primaryKey('partner_code');
$this->hasMany('TradingPartnerAddresses', [
'foreignKey' => 'partner_code'
]);
}
Trading Partner Addresses Table
public function initialize(array $config) {
$this->entityClass('App\Model\Entity\TradingPartnerAddress');
$this->belongsTo('TradingPartners', [
'foreignKey' => 'partner_code'
]);
}
debug($patchedEtentites);
(int) 0 => object(App\Model\Entity\TradingPartner) {
.....
'trading_partner_addresses' => [],
'[new]' => false,
'[accessible]' => [
'*' => true
],
'[dirty]' => [
'trading_partner_addresses' => true
],
'[original]' => [],
'[virtual]' => [],
'[errors]' => [],
'[repository]' => 'TradingPartners'
Any Ideas why the trading_partner_addresses is being flagged as dirty when it's actually clean?
When u patch an entity with some data it's automatically flagged as dirty
$tradingPartners->patchEntities($currentTradingPartners, $partners);
It means you are updating $currentTradingPartners with $partners data so $currentTradingPartners is modified and marked to dirty.
If u want the original data u can use getOriginal method on your entiy's properties, u can also remove the dirty flag with the clean method.
If u got problem to patch entities with associations u must pass an array of options in patchEntity:
$article = $articles->get(1);
$articles->patchEntity($article, $this->request->data(), [
'associated' => ['Tags', 'Comments.Users']
]);