-2
データベーステーブルにソート列を使用しています。 新しいデータエントリを保存するたびに、ソートの最大カウントを選択し、この新しいソート番号を新しいエントリに保存したいと考えています。Cakephp3:最大カウント発注番号を保存
cakephp3でどうすればいいですか?
データベーステーブルにソート列を使用しています。 新しいデータエントリを保存するたびに、ソートの最大カウントを選択し、この新しいソート番号を新しいエントリに保存したいと考えています。Cakephp3:最大カウント発注番号を保存
cakephp3でどうすればいいですか?
私は(残念ながらどこ...すべてのクレジット原作者に覚えていない)しばらく前にこのコードを発見し、自分のニーズに合わせて
を少し編集したソートの
を使用したいtable
にこれを追加
$this->addBehavior('Sortable', [
'field' => 'sort'
]);
と、これは自動にインクリメントソート値を追加し、また、提供することができ/src/Model/Behaviour/SortableBehaviour.php
<?php
namespace App\Model\Behavior;
use Cake\Database\Expression\QueryExpression;
use Cake\Event\Event;
use Cake\ORM\Behavior;
use Cake\ORM\Entity;
use Cake\ORM\Exception\RecordNotFoundException;
use Cake\ORM\Table;
use Cake\ORM\Query;
class SortableBehavior extends Behavior {
protected $_table;
/**
* Default config
*
* These are merged with user-provided config when the behavior is used.
*
* field
* - the field in the DB-table that is doing the sorting
* scope
* - one or more foreign_keys as array
* - eg ['user_group_id'] in a table users would enabled sorting for each
* - user_group separately
* newEntries
* - either `last` or `first`
*
* @var array
*/
protected $_defaultConfig = [
'field' => 'sort',
'scope' => null,
'newEntries' => 'last'
];
/**
* Constructor
*
* @param \Cake\ORM\Table $table The table this behavior is attached to.
* @param array $config The config for this behavior.
*/
public function __construct(Table $table, array $config = []) {
parent::__construct($table, $config);
$this->_table = $table;
}
/**
* Before save listener
* handles initial sorting for added entities
* @param \Cake\Event\Event $event The beforeSave event that was fired
* @param \Cake\ORM\Entity $entity the entity that is going to be saved
* @return void
*/
public function beforeSave(Event $event, Entity $entity) {
$config = $this->config();
if (!$entity->isNew()) {
return;
}
if ($config['newEntries'] == 'last') {
$scopeData = $this->_getScopeData($entity);
$maxPosition = $this->_getMaxPosition($scopeData);
$entity->set($config['field'], $maxPosition + 1);
}
}
/**
* After delete listener
*
* makes sure the left over entities are sorted properly
*
* @param \Cake\Event\Event $event The afterDelete event that was fired
* @param \Cake\ORM\Entity $entity the entity that was going to be deleted
* @return void
*/
public function afterDelete(Event $event, Entity $entity) {
$config = $this->config();
$expression = new QueryExpression($config['field'] . ' = ' . $config['field'] . ' - 1');
$conditions = [
$config['field'].' >' => $entity->get($config['field'])
];
$conditions += $this->_getScopeData($entity);
$this->_table->updateAll($expression, $conditions);
}
/**
* main move method
*
*
*
* @param integer $id the id of the Entity that was moved
* @param array $newSortOrder all IDs of the current scope in the desired sort order (as provided by http://johnny.github.io/jquery-sortable/)
* @return boolean
*
*/
public function move($id, $newSortOrder) {
return $this->_table->connection()->transactional(function() use ($id, $newSortOrder) {
return $this->_move($id, $newSortOrder);
});
}
/**
* helper method that contains the actual move code
*
* @param integer $id the id of the Entity that was moved
* @param array $newSortOrder all IDs of the current scope in the desired sort order (as provided by http://johnny.github.io/jquery-sortable/)
* @return boolean
*
*/
protected function _move($id, $newSortOrder) {
$config = $this->config();
$node = $this->_getNode($id);
$current_position = $node[$config['field']];
// might be faster to do array_flip?!
$new_position = array_search($id, $newSortOrder) + 1;
// no position change -> return
if ($current_position == $new_position) {
return true;
}
// build sql for updating affected entries
if ($current_position < $new_position) {
$expression = new QueryExpression($config['field'] . ' = ' . $config['field'] . ' - 1');
$conditions = [
'sort >' => $current_position,
'AND' => [ $config['field'].' <=' => $new_position ],
];
} else {
$expression = new QueryExpression($config['field'] . ' = ' . $config['field'] . ' + 1');
$conditions = [
'sort <' => $current_position,
'AND' => [ $config['field'].' >=' => $new_position ],
];
}
$conditions += $this->_getScopeData($node);
$res = $this->_table->updateAll($expression, $conditions);
// finally set the inital field to the new val
$q = $this->_table->query();
return $res && $q->update()
->set([$config['field']=>$new_position])
->where(['id'=>$id])
->execute();
}
/**
* returns a node and the scope params if set up in config
* @param integer $id the node id
* @return Array|Object the result of query->first()
* @throws Cake\ORM\Exception\RecordNotFoundException if no node with that id found
*/
protected function _getNode($id) {
$config = $this->config();
// get current sort of `id`
// if a context is set -> get that also while we are aclling this
$query = $this->_table->find();
$query
->select(array_merge(['id', $config['field']], (array)$config['scope']))
->where(['id'=>$id])
->contain();
if (!$node = $query->first()) {
throw new RecordNotFoundException(sprintf('Kein Eintrag mit ID %s gefunden', $id));
}
return $node;
}
/**
* returns the highest position within that scope
*
* @param array $scopeData the scope data
* @return integer the currently highest positions in that scope
*/
protected function _getMaxPosition($scopeData=null) {
$config = $this->config();
$query = $this->_table->find();
$query
->select(array_merge([$config['field']], array_keys($scopeData)))
->where($scopeData)
->order([$config['field'] => 'DESC'])
->contain();
$node = $query->first();
return ($node[$config['field']] ?: 0);
}
protected function _getScopeData($node) {
$config = $this->config();
$conditions = [];
foreach ((array)$config['scope'] as $scope) {
$conditions[$scope] = $node[$scope];
}
return $conditions;
}
}
でこれを保存します並べ替え(コントローラクラスへの操作が必要)
希望するもの