PHP: Self-referencing array
The answer to this, as it turns out, is Yes. However it is not a tidy syntax as it uses a sort of sub-statement, and leaves the current scope littered with an extra reference variable.
Consider the following code:
<?php
$array = array(
// Creates Key1 and assigns the value to it
// A copy of the value is also placed in $ref
// At this stage, it's not a reference
"Key1"=>($ref = array(
"Value1",
"Value2"
)),
// Now Key2 is a reference to $ref, but not to Key1
"Key2"=>&$ref,
// Now everything is referenced together
"Key1"=>&$ref
);
I was surprised that this worked with no errors, but it does - here's the proof. Of course, you wouldn't do this, but you can...
PHP Self-referencing script
You must verify that you was send the page and $_POST exist. And correct the select element
<form action = "<?php $_SERVER['PHP_SELF'] ?>" method = "post">
<input type = "number" id = "temp2" name = "temperature2" placeholder = "28">
<label for = "temp2"> degrees </label>
<select name = "conv">
<option value = "f"> Fahrenheit </option>
<option value = "c"> Celsius </option>
</select>
<input type = "submit" value = "equals">
<?php
if(isset($_POST["temperature2"])) {
$type = $_POST["conv"];
$tmp = $_POST["temperature2"];
if ($type == "f") {
$newTmp = (9/5 * $tmp) + 32;
echo $newTmp . " degrees Celsius.";
}
elseif ($type == "c") {
$newTmp = (5 * ($tmp - 32)) / 9;
echo $newTmp . " degrees Fahrenheit.";
}
}
?>
</form>
self-referencing table and arrays
Your table structure is fine.
You'll render the nesting when you deal with the results; perhaps you loop through each result with no parent and append to the DOM, then loop through each result with a parent appending to existing elements. That only works for a two-level tree, but you get the idea.
Create Nested Array From Database Self Referencing Table And Show in Nested list In Smarty Template
You can use recursive function like this:
function addToArr(&$arr, $data) {
if ($data["parent_id"] == 0)
return $arr[] = ["id" => $data["id"], "name" => $data["name"], "children"=> []];
foreach($arr as &$e) {
if ($e["id"] == $data["parent_id"]) { // if found add as child
$e["children"][] = ["id" => $data["id"], "name" => $data["name"], "children"=> []];
break;
}
addToArr($e["children"], $data); // call recursively
}
}
Live example: 3v4l
Edit
To have HTML tag:
function getHTMLformat($arr) {
if (!$arr) return "";
$str = "<ul>" . PHP_EOL; // starting the list
foreach ($arr as $e) {
$str .= "<li>" . $e["name"] . getHTMLformat($e["children"]) . "</li>" . PHP_EOL;
}
return $str . "</ul>" . PHP_EOL; // end list
}
echo getHTMLformat($res);
Reference key from same array
You can use the fact that assignment is itself an expression in PHP:
$glossary_args = array(
'name' => ($name = 'Glossary Terms'),
'singular_name' => 'Glossary Term',
'add_new' => 'Add New Term',
'edit_item' => 'Edit Term',
'search_items' => 'Search'.$name
)
Form with self-referencing data (Symfony 5)
The answer from Dylan Kas was good, just by adding a new form, it's good.
The Person Form
class PersonType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('name', TextType::class, ['attr' => ['class' => 'form_textfield']])
->add('firstname')
->add('birthdayDate', TextType::class, ['attr' => ['class' => 'form_datetime']])
->add('gender', GenderType::class)
->add('submit', SubmitType::class)
->add('myFamily', CollectionType::class, array('entry_type' => ChildType::class, 'by_reference' => false, 'allow_add' => true, 'allow_delete' => true));
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Person::class,
]);
}
}
The child, referenced by myFamily :
class ChildType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('name', TextType::class, ['attr' => ['class' => 'form_textfield']])
->add('firstname')
->add('birthdayDate', TextType::class, ['attr' => ['class' => 'form_datetime']])
->add('gender', GenderType::class)
->add('submit', SubmitType::class);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Person::class,
]);
}
}
And the view :
{% block body %}
{{ form_start(form) }}
{{ form_row(form.name) }}
{{ form_row(form.firstname) }}
{{ form_row(form.birthdayDate) }}
{{ form_row(form.gender) }}
<button type="button" class="add_item_link" data-collection-holder-class="myFamily">Add a tag</button>
<ul class="myFamily" data-index="{{ form.myFamily|length > 0 ? form.myFamily|last.vars.name + 1 : 0 }}" data-prototype="{{ form_widget(form.myFamily.vars.prototype)|e('html_attr') }}"></ul>
{{ form_end(form) }}
{% endblock %}
With the js associated
const addFormToCollection = (e) => {
const collectionHolder = document.querySelector(
"." + e.currentTarget.dataset.collectionHolderClass
);
const item = document.createElement("li");
item.innerHTML = collectionHolder.dataset.prototype.replace(
/__name__/g,
collectionHolder.dataset.index
);
collectionHolder.appendChild(item);
collectionHolder.dataset.index++;
};
document
.querySelectorAll(".add_item_link")
.forEach((btn) => btn.addEventListener("click", addFormToCollection));
It still need some work, maybe I can make the child form extending the person form. The front need some work too. But the next people facing this problem will have the solution here.
I am still asking myself how could I do if I've needed to have a form including itself the same form, including itself the same form etc...
The form would be recursivable.
PHP function pass by reference self::$menus
You are passing it in as a recursive call here:
self::addChild($item_id, $title, $url, $parent_id, $value);
Which might be better as:
static::addChild($item_id, $title, $url, $parent_id, $value);
So just use static::$menus
instead of $array
if nothing was passed in:
public static function addChild($item_id, $title, $url, $parent_id, &$array=null)
{
if($array === null) {
$array = &static::$menus;
}
// other code
}
Or this might be better since you actually need an array:
if(!is_array($array)) {
$array = &static::$menus;
}
Then for the main calls (not recursive) just omit the $array parameter.
- What is the difference between self::$bar and static::$bar in PHP?
- PHP Manual - Late Static Bindings
Is it possible for a variable to reference itself
So, thanks to RandomSeed reminding me of variable references, I came up with what I think is the closest solution I'm likely to get.
Take this as an example:
$array['index1']['index2']['index3']['index4'];
$array['index1']['index2']['index3']['index4'] = array_merge(
$array['index1']['index2']['index3']['index4'],
array('test' => 'answer'),
array('test2' => 'answer'));
This is unappealing in my eyes, and a bit difficult to follow, especially if there are multiple of these on a page, or in a controller action.
So this is an alternative:
$self = &$array['index1']['index2']['index3']['index4'];
$array['index1']['index2']['index3']['index4'] = array_merge(
$self,
array('test' => 'answer'),
array('test2' => 'answer'));
A Quick test on my live environment seems to verify that it works.
Related Topics
Codeigniter Assets Folder Best Practice
What Is 22527 in Error_Reporting 22527 of PHPinfo
What's the Difference Between Is_Null($Var) and ($Var === Null)
Wordpress Plugin -> Call to Undefined Function Wp_Get_Current_User()
Laravel Pluck Fields from Relations
Chart.Js - Getting Data from Database Using MySQL and PHP
Get "Content-Type" Header of Request in PHP
PHP - Listing All Directories and Sub-Directories Recursively in Drop Down Menu
How to Use PHP in a JavaScript Function
Php's File_Exists() Will Not Work for Me
Required_If Laravel 5 Validation
PHP MySQL - Insert New Record into Table with Auto-Increment on Primary Key
Can a User Alter the Value of $_Session in PHP