Require one of several values - cakephp

I have a table with 5 boolean columns. I want to force the user to pick at least one. Is there a way to do this using the CakePHP $validator object in the Table PHP?
I can accomplish this in the controller easy enough, but utilizing the built-in stuff seems less wrong. Nothing in the docs jumps out at me. .
Controller example:
if (false === $val1 === $val2 === $val3 === $val4 === $val5){
//return with error
}

This would seem to be a situation for a rule, not a validation.
public function buildRules(RulesChecker $rules) {
$rules->add(function (EntityInterface $entity, Array $options) {
return $entity->val1 || $entity->val2 || $entity->val3 || $entity->val4 || $entity->val5;
}, 'selectOne', [
'errorField' => 'val1',
'message' => __('You must select at least one of these fields.'),
]);
return $rules;
}

Related

Speeding up a very slow Vuetify Filter method

I have a working filter method, however it is very slow. text input is passed into $store, and a function is applied to see if anything in an array is a partial match for the text-input. Essentially I am using a computed function to iterate over to display components.
This is effectively the first thing I've tried. It does work in some capacity, but is unbelievably slow and unoptimized.
<v-flex
v-for="myFolder in folderFilter"
:key="myFolder"
xl2
md4
xs6
justfy-space-around
style="padding-top:50px;"
>
<FolderIcon
:folderName="myFolder.folderName"
:folderDescription="myFolder.folderDescription"
:isReadOnly="myFolder.isReadOnly"
:addImage="myFolder.addImage"
:updateHeader="myFolder.updateHeader"
></FolderIcon>
</v-flex>
computed: {
folderFilter(): Folder[] {
let returnFolder: Folder[] = new Array();
if (
this.$store.state.search === "" ||
this.$store.state.search === null
) {
return this.$store.state.displayArray;
} else {
this.$store.state.displayArray.forEach((element: Folder) => {
if (
element.folderName
.toLowerCase()
.includes(this.$store.state.search.toLowerCase())
) {
returnFolder.push(element);
}
});
}
return returnFolder;
}
},
It does work, however when I add more input it is very laggy to take input.

Select from table where both columns have same value

I have the code that selects all articles. What I am doing is, I think, wrong. I am selecting all values and then I am executing them.
Article::all()->each(function($article) {
if ($article->created_at == $article->published_at && $article>published) {
$article->update(['published_at' => null]);
}
});
What I need to do is select only those articles that have the mentioned created_at and updated_at the same.
How could I do that on the database level?
I need sth like that:
Article::where('created_at', '=', 'published_at')->where('published')->get()->each(function($article) {
$article->update(['published_at' => null]);
}
});
This code sure does not work, its just for imagine.
edit your code
Article::all()->each(function($article) {
if ($article->created_at == $article->published_at && $article->published) {
$article->update(['published_at' => null]);
}
});
You only need to search on the two columns for the one value:
Article::where(['created_at' => $date, 'updated_at' => $date ])->get();
Edit:
Use whereRaw for this
Article::whereRaw('created_at = updated_at')->get();

Multiple matching() and contain(), condition on related records count

With CakePHP 3.x, I have 3 models : StudentProfile, Diploma1 and Diploma2.
StudentProfile hasMany Diploma1
StudentProfile hasMany Diploma2
Diploma1 has an integer "state" field.
I need to get StudentProfiles which :
have one (or more) related Diploma1 where Diploma1.state = 2
OR
have one (or more) Diploma2 (no condition on Diploma2 fields)
I need to retrieve the matching Diploma1 and Diploma2 with my StudentProfiles.
I'm using the Search and Paginator components, so I have to do this with one query.
For now, I'v been able to get the first part by doing :
$query = $this->StudentProfiles
->find('search', $this->StudentProfiles->filterParams($this->request->query))
->contain(['Diploma1' => function ($q) {
return $q->where(['Diploma1.state' => 2]);
}])
->matching('Diploma1', function($q) {
return $q->where(['Diploma1.state' => 2]);
})
->distinct(['StudentProfiles.id'])
;
$this->set('studentProfiles', $this->paginate($query));
Combining matching and contain allows me to add the condition and get related Diploma1 (as I understand it).
Now I need to get also all the StudentProfiles with a related Diploma2, this is where I get stuck. If I add
->contain(['Diploma2'])
...to my query, I only get Diploma2 for StudentProfiles that have a matching Diploma1 (where state=2), but I don't get StudentProfiles with related Diploma2 only (without matching Diploma1), which is perfectly normal.
So I have 2 questions :
how can I get all StudentProfiles that have a related Diploma2 (i.e add a condition using count(...) > 0 maybe ?)
how can I combine this with a matching clause with a condition (state=2) ?
I hope this is clear.
Thanks
A slightly different approach, but maybe it helps
$query = $this->Profile->find();
$query->select([
'Profile.id',
'Profile.name',
'D1.id',
'D1.name',
'D1.status',
'D1.profile_id',
'D2.id',
'D2.name',
'D2.status',
'D2.profile_id',
'd1c' => 'COUNT(D1.id)',
'd2c' => 'COUNT(D2.id)',
]);
$query->contain([
'D1' => function($q) {
$q->where(['D1.status' => 2]);
return $q;
},
'D2'
]);
$query->leftJoinWith('D1', function($q) {
return $q->where(['D1.status' => 2]);
});
$query->leftJoinWith('D2', function($q) {
return $q;
});
$query->having(function($q) {
return $q->or_([
'd1c >' => 0,
'd2c >' => 0,
]);
});
$query->group('Profile.id');
I couldn't really get contain to create a join, so I had to add those leftJoinWith

How to ensure only one record is active

I want that when a record is saved and marked as active, all other records are marked INactive.
I've tried the following code in my model:
public function beforeSave($options = array()) {
if (!empty($this->data['Ticket']['is_active'])) {
$this->data['Ticket']['is_active'] = 0;
}
return true;
}
However this code is error
Use afterSave
Instead of using beforeSave, it's more appropriate to use afterSave, and updateAll like so:
public function afterSave($created) {
if (!empty($this->data[$this->alias]['is_active'])) {
$this->updateAll(
array('is_active' => 0),
array(
'id !=' => $this->id,
'is_active' => 1
)
);
}
}
I.e. after successfully saving a record, if it is active disable all the others.
Note: be sure to use the same method signature as the parent class. It varies depending on which version of CakePHP you are using.
You can write before save method like
public function beforeSave($options=array()){
if (!empty($this->data[$this->alias]['is_active'])) {
$this->data[$this->alias]['is_active'] = 0;
}
return true;
}

How to define a checkbox variable in Cakephp

I have a form in my Plugin elements and what i would like to insert the checkbox value into a table named it_queries and field status_type and its giving me an error Undefined variable: variableValue [APP\Plugin\Feedback\View\Elements\comment_add.ctp, line 37] .I have declared the variable in my controller like this
$this->set('variableValueStatus', 'Pending');
and this is line 37 thats giving me the error
Below is the Controller code
App::uses('FeedbackAppController', 'Feedback.Controller');
class CommentsController extends FeedbackAppController
{
public $components = array('Feedback.Comments');
public function add($foreign_model = null, $foreign_id = null)
{
if (empty($foreign_model) ||
empty($foreign_id) ||
!$this->request->is('post')
)
{
foreach ($_POST['likebutton'] as $pageId => $likeFlag) {
$dbFlag = $likeFlag ? 'Yes' : 'No';
}
return $this->redirect('/');
}
App::uses($foreign_model, 'Model');
$Model = ClassRegistry::init($foreign_model);
if (!($Model instanceof Model))
{
return $this->redirect('/');
}
if ($Model->hasAny(array($Model->primaryKey => $foreign_id)) == false)
{
return $this->redirect('/');
}
if (!isset($this->request->data['Comment']['foreign_model']) ||
!isset($this->request->data['Comment']['foreign_id']) ||
$this->request->data['Comment']['foreign_model'] != $foreign_model ||
$this->request->data['Comment']['foreign_id'] != $foreign_id)
{
return $this->redirect('/');
}
$user_id = null;
if (isset($this->Auth))
{
$user_id = $this->Auth->user('id');
}
$this->request->data['Comment']['foreign_model'] = $Model->name;
$this->request->data['Comment']['foreign_id'] = $foreign_id;
$this->request->data['Comment']['user_id'] = $user_id;
$this->Comment->create();
if (!$this->Comment->save($this->request->data))
{
$this->set('validation_errors', $this->Comment->validationErrors);
return;
}
$this->redirect($this->request->referer().'#comment-'.$this->Comment->id);
}
}
and in the add view in my element here is how i am trying to accessing the variable value
echo $this->Form->checkbox('ItQuery.status_type', array('type' => 'hidden', 'value'=>$variableValueStatus));
If someone can show me how to fix this, that would be awesome
You are only passing the variable down on !post and if foreign model and foreign id are not set.
That will most likely not work in most of the cases.
You should be always passing down a variable if you do not check on it in the view prior to using it.
But it would still be wrong, anyway. You would have to use "default" instead of "value" if you dont want your form to fall back on the old value on POST (which it shouldnt).
Also, it is always better to use $this->request->data to properly fill the form with defaults:
if (!$this->request->is('post')) {
$this->request->data['ItQuery']['status_type'] = 'Pending';
}
See working-with-forms

Resources