October CMS backend list's column get array key value - php

Hi I'm new to October cms . I have defined the below shown method in my model class. The method is also used to show the select options in the backend form. This method returns an array where the key is a value similar to a field value in db. I have defined the method as static because it is also recommended in the front end where I get the function and process it with db record and iterate it to show the value of the array that matches the key. It all works fine. Thing is in my columns.yaml file, how do I list the method's array value which matches the db record as I did in front end.
public static function getSampleOptions()
{
return[
'1'=>'Sample1',
'2'=>'Sample2'
];
}

Hello friends I found the answer with some help from October CMS Help/Support
http://octobercms.com/index.php/forum/post/dropdown-shows-its-value-than-key-name-in-list-controller
and referred few concepts of laravel.
Model Class Method
public static function getSampleOptions()
{
return[
'1'=>'Mobile App',
'2'=>'Web App'
];
}
Columns.Yaml file
sample:
label: Sample Column
type: dropdown
Again back in the model, declare the attributes object and include the filed name as key with empty value
public $attributes = ['sample'=>''];
Define the getfield_nameAttribute() function to set the associated value for the appropriate key in the column
public function getSampleAttribute()
{
$result = $this->attributes['sample'];
$options = $this->getSampleOptions();
foreach($options as $key=>$value)
{
if($key == $result)
{
return $value;
}
}
}
Updated
The solution to rectify the problem while editing the record is simple.
Create a partial and modify the fields. yaml
_sample_options.htm (partial) // file name should begin with_(underscore)
<?php
$fieldOptions = $model->getSampleOptions();
$sample = $model->attributes['sample'];
?>
<select id="<?= $field->getId() ?>" name="<?= $field->getName() ?>" class="form-control custom-select" <?= $field->getAttributes() ?>>
<?php foreach($fieldOptions as $key=>$label)
{
?>
<option value="<?= $key ?>" <?php echo ($sample == $key)?"selected":''; ?>><?= $label ?></option>
<?php
} ?>
</select>
Here the $model and $field are the partial variables that are used to access the intended model's methods and properties.
Documentation : https://octobercms.com/docs/backend/forms#field-partial
Fields.Yaml file
sample:
label: Sample Field
type: partial
path: $/october/demo/controllers/sample/_sample_options.htm //path where the partial is located in the controller view

break a for loop in october cms template if condition not satisfied?
{% for key, pTest in pack.products %}
{{loop.length}}
<li>{{pTest.productable.name}} {{ key }}</li>
{% if key == 2 %}
<li class="more">...</li>
{% endif %}
{% endfor %}

Related

How to properly count template usage?

I'm using Symfony 6.1 with Twig on PHP 8.1. I've already set up my complete layout including fragments/partials/components or whatever we call reusable pieces of the layout at the moment. These fragments include certain kinds of navigations, quotes, tabs and so on which are always supposed to look and work the same and usually only receive a variable with the same name as an array with a few options.
This is how I'm embedding a YouTube-Video for example:
{% set youtube_video = { 'id': 'dQw4w9WgXcQ', 'title': 'Secret Video (unlisted)', 'language': 'en' } %} {% include 'fragment/youtube_video.html.twig' %}
Most of these fragments can be used multiple times on one page (= in the main template of the view or within the base template/s). Some of them however are supposed to be used only once and using them multiple times would create layout issues (e.g. a navigation for mobile devices with a specific CSS id).
For other fragments I would like to have a counter to add a CSS id in addition to a normal class:
<div class="fragment_video" id="fragment_video_{{ counter }}> ... </div>
The question now is how I can count within a fragment template like 'fragment/youtube_video.html.twig' how often this template has been used in that page already. I don't see any Twig functions or anything within the "app" variable for that.
Now I could create a custom Twig function "counter" and call that with with a unique name:
<div class="fragment_video" id="fragment_video_{{ counter('fragment_video') }}> ... </div>
or
{% if counter('fragment_video') == 1 %} ... {% endif %}
BUT how would I store the current count per given name? I don't want to use $GLOBALS in Twig or rather Symfony and storing that information in the session would keep it past the current request. Is there another solution available?
This is how it would look like as a Twig function:
public function getCounter(string $name): int
{
$name = 'twig_counter_'.$name;
if (isset($GLOBALS[$name])) {
++$GLOBALS[$name];
} else {
$GLOBALS[$name] = 1;
}
return $GLOBALS[$name];
}
As suggested by #DarkBee the instance of a TwigExtension object can use properties to keep track of some information:
/**
* #var array<int>
*/
private array $count = [];
...
public function getCounter(string $name): int
{
if (isset($this->count[$name])) {
++$this->count[$name];
} else {
$this->count[$name] = 1;
}
return $this->count[$name];
}

calculate the number of points and save the result in the user profile database

So I have a form containing questions of type free fields (text), multiple choice (checkbox), single choice (radio).
I get the values ​​of the button checked and I save in database for each user but what I want to do is change this value like this:
data-point "2" = 10 points,
data-point "3" = 7 points,
data-point "4" = 4 points,
data-point "5" = 2 points,
and then with these values ​​I have to do a calculation and define a profile according to the result .. how should I do that? SQL request? in the loop? a little help would be welcome ..here my twig to loop on subquestion.
<div class=" col-6 d-flex">
<div class="label-div1">
<label for="subscale{{subQuestion.id}}for{{i}}>
<img src="{{asset('images/survey/humeur/'~ i ~'.jpg')}}">
</label>
<input type="radio" class="radio-pict" name="{{subQuestion.id}}" id="subscale{{i}}" data-point="{{i}}"value="{{i}}">
</div>
here my controller to save de answers
public function saveAnswer(Request $request)
{
/* Repository */
$questionRepo = $this->getDoctrine()->getRepository(Question::class);
$answerRepo = $this->getDoctrine()->getRepository(Answer::class);
$choiceRepo = $this->getDoctrine()->getRepository(Choice::class);
$userSlpRepo = $this->getDoctrine()->getRepository(UserSlp::class);
/* Entity Manager */
$em = $this->getDoctrine()->getManager();
$datas = $request->request->all();
$userSlp = $userSlpRepo->findOneByGaeaUserId($this->getUser()->getId());
foreach ($datas as $data => $value) {
$questionId = explode("_", $data);
$question = $questionRepo->findOneById($questionId[0]);
switch ($question) {
case 'Sub_question_free':
$answer = new Answer_free;
$answer->setFreeAswere($value);
break;
case 'Sub_question_scale':
$answer = new Answer_scale;
$answer->setScale($value);
break;
$answer->setQuestion($question);
$answer->setUserSlp($userSlp);
$em->persist($answer);
$em->flush();
}
exit;
}
}
and here my twig to display on admin the results..
{% if answer.question == "Sub_question_choice" or
answer.question == "Sub_question_scale" or
answer.question == "Sub_question_free" %}
{% if answer == "choice" %}
{% for choice in answer.choices %}
<p>{{choice.name}}</p>
{% endfor %}
{% elseif answer == "free" %}
<p>{{answer.freeAswere}}</p>
{% elseif answer == "scale" %}
<p> {{answer.scale}}</p>
{% endif %}
So first, in Symfony a controller always need to send back a response. Even if it's just a redirect or a JsonResponse. So you shouldn't use exit in your controller.
You should use Symfony form, but if you are new to Symfony, I can understand that it's not easy.
Here to help you, you have many options:
You can change value with some conditions inside your swith statement in your controller
You can separate that in a service, look for service in Symfony on the docs. And use dependency injection inside your controller like this :
Service :
public function conversion(){
//Some conditions
}
controller:
public function saveAnswer(Request $request, YourService $service)
And use it inside as a function.
(More Easy Option) You can overload your setter in your entity (Answer.php for example):
public function yourSetter(...){
//do some conditions and after set your variables depending on result
}
Hope this will help you, feel free to ask if you want !

How to work with a phalcon variable inside PHP?

I created a variable inside a controller :
<?php
use Phalcon\Mvc\Controller;
class RestaurantreservationController extends Controller
{
public function indexAction(){
return $this->view->pick("reservation/listerReservation");
}
public function affecterReservTableAction($id) {
$this->view->action_form = 'affecterReservTableExec';
$this->view->titre = 'Réservation de table';
$this->view->table_code = $id; // here is the variable I want to manipulate
return $this->view->pick("reservation/reservTable");
}
}
?>
Inside the view reservTable.phtml I want to work with the variable table_code :
<div class="input-control select">
<select name="clt_id" id="clt_id">
<option value="">--Choisir une table--</option>
<?php
$table_code = {{table_code}}; // it generates an error
$tables = TableClient::lireParCritere([]);
foreach ($tables as $table) {
$select = ($table_code == $table->table_code ? "selected" : "" );
?>
<option <?php echo $select; ?> value="<?php echo $table->table_code; ?>"><?php echo $table->noms; ?></option>
<?php
}
?>
</select>
</div>
How can I use it to set as the selected element of the select element ?
The problem is you are mixing phtml and Volt syntaxes when you try to assign {{table_code}} to $table_code.
The Volt variable {{ table_code }} is the same as $table_code.
If you use Phalcon then it is good to use VOLT
When you create Volt type of template you can access variable by {{ table_code }}
If you wan't loop you can use something like
{% for table in tables %}
//do something
{% endfor %}
Volt has also nice function to create selects
{{ select("table", table_code, 'using': ['table_code', 'table_noms']) }}
Volt documentation
Select in Volt
You used it correctly three lines further down the code. At the point you're trying to use the variable, you're in PHP mode. That means you just write PHP code, i.e. $table_code. The form {{table_code}} is for interpolation inside a VOLT template, not for use inside PHP code.
I would actually recommend converting all of that PHP block into VOLT template code.

Form element validation in Phalcon framework (check if element exists)

I am beginner in Phalcon framework, I have to validate form elements in .volt page
I have one form class file where I write hidden filed for record edit purpose, I'm storing record's id in hidden filed when its in edit mode
if ($options["edit"] == 1) {
// $tax_categories_id = new Hidden("tax_categories_id");
$this->add(new Hidden('tax_categories_id'));
//$this->add($tax_categories_id);
}
The problem is when I rendering this hidden filed in add.volt
{{ form.render('tax_categories_id')}}
Its working fine in time of edit mode, but in new record time its give error
Phalcon\Forms\Exception: Element with ID=tax_categories_id is not a part of the form
I know the why error is coming but i am not able to validate this field in .volt file
In the controller can you set your $options variable and then check for it inside of the view?
//controller.php
$this->view->setVar('options', $options);
//view.volt
{% if options['edit'] %}
{{ form.render('tax_categories_id')}}
{% endif %]
Just check if the element is exist
// add.volt
{% if form.has('tax_categories_id') %}
{{ form.render('tax_categories_id') }}
{% endif %}
Assuming you have crated something close to:
<?php
use Phalcon\Forms\Form,
Phalcon\Forms\Element\Text,
Phalcon\Forms\Element\Hidden;
class UsersForm extends Form
{
public function initialize($options = [])
{
if ( isset($options['edit']) && $options['edit'] ) {
$this->add(new Hidden('id'));
}
$this->add(new Text('name'));
}
}
So! Depending on options, you may have one field declared, or two instead. Now when someone sends you this form back, for validation you have to set it up again with proper $options['edit'], depending on if you have $_REQUEST['id'] declared or not:
$form = null;
if( isset($_REQUEST['id']) ) {
$form = new UsersForm();
} else {
$form = new UsersForm(['edit' => true]);
}
$form->bind($_REQUEST);
if($form->isValid()) {
//...
}
Quite an advanced (but with some gaps anyway) manual is here. Bet you were there already, but just in case.
Btw, form are iterators & traversables, so you can loop over them to render only elements, that are declared. Writing this because you have put {{ form.render('tax_categories_id')}} as an example and that makes me feel like you are generating fields by hand.

Twig - Loop returns only 1 result

i'm trying to make a loop in php while using twig and inside this loop,
i am creating a parameter which contains the record from the database query.
The problem is that when I use the parameter in my HTML file, it only return 1 record from the while loop, even if there are 3 or 4 or even more..
This is the php code I have:
public function getWidgetsByName($name)
{
global $params;
$get = $this->db->query("SELECT * FROM profile_items
WHERE category = 'widget'
AND username = '". $name ."'");
if($get)
{
while($key = $get->fetch())
{
$params["profile_widget_name"] = $key['name'];
}
}
}
And this is the HTML parameter in my HTML twig rendered file:
{{ profile_widget_name }}
The paremeters just get rendered how they are supposed to be rendered:
echo $twig->render('app/views/'. $_REQUEST['p'] .'.html', $params);
And yes the $params variable is an array, in the config it file it first gets used as $params = array("..." => "..."); and I add things to this array by doing $params["..."] = "...";
So, I hope someone can help me.
Thanks in advance,
Best Regards.
At the moment, the value of $params["profile_widget_name"] is just one string. Every time you go through the while loop, you overwrite the previous value of the key with the current value.
So when you pass $params to Twig, the value of profile_widget_name is the value of name in the last row of the database to be selected.
I think what you want instead is for the value of profile_widget_name to be an array. Then every time you go through the loop, the current value of name is added to the array, instead of overwriting it.
You do this by doing something like:
$params["profile_widget_names"][] = $key['name'];
Now in your Twig template, you'll need to do something like:
{% for profile_widget_name in profile_widget_names %}
{{ profile_widget_name }}
{% endfor %}
Using Multiple Parameters
If you want multiple parameters to be on there, you can do this:
$params["profile_widgets"][] = [
'pos_x' => $key['pos_x'],
'name' => $key['name'],
];
And in Twig:
{% for profile_widget in profile_widgets %}
Name: {{ profile_widget.name }}
Pos X: {{ profile_widget.pos_x }}
{% endfor %}

Categories