• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Formularz - Nieokreślona liczba zmiennych, a zapytanie SQL

Object Storage Arubacloud
0 głosów
410 wizyt
pytanie zadane 13 listopada 2018 w SQL, bazy danych przez progNewbie Obywatel (1,130 p.)

Hej Wam! 

Od razu na wstępie piszę, że nie proszę o kod, a nakierowanie, logikę, podpowiedzi czego użyć.

Chciałbym napisać formularz, gdzie będą: inputy[text], checkboxy lub optiony wielokrotnego wyboru, do których będą przypisane stanowiska.

I teraz chciałbym stworzyć (może pętle), która obsługiwałaby zapytanie SQL, które miałoby na celu przypisywanie zawartości inputów[text] do stanowisk. 

Każde stanowisko wymienione w checkboxach lub optionach ma identyczną nazwę jak nazwy tabel w bazie danych.

Problemem dla mnie jest to aby wymyślić jak to napisać aby skrypt poprawnie działał, nie wiedząc ile tych optionów zostanie zaznaczonych przez usera.

 

Mam w sumie 2 pomysły:

1. Albo użyć inputów i wtedy dla każdego checkboxa = true jego nazwę przypisywać do tablicy.

Wrzucić to w pętlę, która by obsłużyła każdą nazwę dodaną do tablicy. Czyli wykonuje się tyle zapytań ile < tablica.lenght - 1 ,  i każde jedno wykonanie się pętli to inna nazwa z tablicy, do której były przypisywane nazwy stanowisk zaznaczonych we formularzu.

2. Albo użyć optionów, ale tutaj nie wiem jak je złapać żeby wbić je do tablicy(nie wiem co zaznaczy user).

3. A może jakoś jeszcze inaczej? Dużo prościej?

 

Zapewne problem jest trywialny, ale niestety nie wiem jak to wyszukać w internecie.

Bardzo proszę o podpowiedzi. Ew. może jakieś lektury, co przeczytać.

1 odpowiedź

+1 głos
odpowiedź 13 listopada 2018 przez Chess Szeryf (76,710 p.)
wybrane 22 listopada 2018 przez progNewbie
 
Najlepsza

Stwórz tablicę już na etapie HTML, np.:

<input type="text" name="trees[]" />

Możesz jeszcze skorzystać z <input type="hidden" .../>.

Jeśli w HTML nadajesz name w standardowy sposób, czyli taki:

<input type="text" name="tree0" />
<input type="text" name="tree1" />

, to na końcu zamiast odwoływać się do zmiennych tak pojedynczo, możesz wrzucić je do np. tablicy, a tablicę w pętlę.

<?php
$trees = [$_POST['tree0'], $_POST['tree1']];

for($i=0;$i<count($trees);$i++) {
   echo $trees[$i];
}
?>

Obsługę błędów zostawiam Tobie (isset, empty).

PIerwsza opcja wyglądałaby tak:

<input type="text" name="trees[]" />
<input type="text" name="trees[]" />
<input type="checkbox" name="trees[]" />

$trees = $_POST['trees'];

for($i=0;$i<count($trees);$i++) {
   echo $trees[$i];
}

Zamiast stosować count<=$var1-1, stosuj zazwyczaj count<$var1. Jeszcze możesz poczytać różnicę między ++$i, a $i++.

<?php

$db_conn = new mysqli('localhost', 'root', 'pass_to_db', 'name_db');

$entry_point = $_POST['trees']; // first option with square brackets ...[] from HTML

$q1 = $db_conn->query('select * from r3');

echo "<table>";

$inc = 0;

while($result = $q1->fetch_assoc()) {
	if(count($result) == count($entry_point)) {
		echo "<tr><td>";
		echo $entry_point[$inc] . '=' . $result['id']."<br />";
		echo $entry_point[$inc] . '=' . $result['tree']."<br />";
		echo "</td></tr>";
		$inc++;
	}
}

echo "<table>";

?>
komentarz 15 listopada 2018 przez Chess Szeryf (76,710 p.)
edycja 15 listopada 2018 przez Chess

"e" znaczy "Event" - zdarzenie.

The Event interface represents any event which takes place in the DOM; some are user-generated (such as mouse or keyboard events), while others are generated by APIs (such as events that indicate an animation has finished running, a video has been paused, and so forth). 

Interfejs Event reprezentuje dowolne zdarzenie, które ma miejsce w DOM; niektóre są generowane przez użytkownika (takie zdarzenia jak mysz lub klawiatura), podczas gdy inne są generowane przez APIs (takie jak: zdarzenia oznaczające zakończenie funkcjonowania (działania) animacji, gdy wideo zostało zatrzymane, i tak dalej).

https://developer.mozilla.org/en-US/docs/Web/API/Event

Poczytaj, w tym link'u powyżej jest to opisane.

https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault

e.preventDefault(); 

Oznacza, zapobiegnij akcji m.in. odświeżenia (przeładowania) strony - zależne od kontekstu w jakim operujemy.

https://developer.mozilla.org/en-US/docs/Web/API/Event/target

var single_sel = e.target.nextElementSibling;

Mówi o tym, żeby (tutaj) znalazł element DOM na, którym nastąpiło ostatnio kliknięcie. Jeśli kliknęłoby się na

<button class="btn">items</button>

, to wtedy ta powyższa instrukcja szuka następnego elementu występującego po tym elemencie, jak sama nazwa wskazuje nextElementSibling. W tym przypadku/przykładzie byłby ten element:

<select name="items[]" multiple="multiple" class="sel">

 

Druga kwestia (CSS), label ma odwołanie to checkbox'a, więc klikając na label klikamy na checkbox'a. Klikając raz, zaznaczasz go, za drugim odznaczasz. Element się pokazuje display:block i chowa, display:none.

~, oznacza - weź wszystkie elementy po tej regule i przypisz im taki styl CSS.

<div id="one">
Text1
</div>

<br />

<div class="two">
Text2
</div>

<br />

<div class="two">
	Text3
	<br />
	<div class="two" style="border:1px dashed black">Text4</div>
</div>

<br /><br /><br />

Wpisz najpierw ~, a później ~* i zobacz efekt.

#one, .two {
	border:1px solid black;
	width:200px;
	height:200px;
}

#one ~ * .two {
	color:lightgreen;
	font-weight:bold;
	font-size:36px;
}

~ * działa tylko na zagnieżdżenie, a ~ na wszytkie elementy, które poprzedza el1 i po którym jest el2:

el1 ~ el2 { } lub el1 ~* el2 {}.

Gdy nabierzesz doświadczenia, to będziesz raczej wiedzieć, dlaczego tak się dzieje. Szlifuj "skill'a" nabierając i teorii (czytanie) i praktyki (wykonywanie).

komentarz 16 listopada 2018 przez progNewbie Obywatel (1,130 p.)
Hej, bardzo Ci dziękuję za tak obszerne wytłumaczenie i naprawdę super podejście.

Generalnie teraz próbuję zaimplementować Twoje podpowiedzi oraz poprzerabiać je pod swoje potrzeby, rezultaty wrzucę później tutaj w formie kodu.

Mam nadzieję, że teraz pójdzie jak po maśle. :)
komentarz 20 listopada 2018 przez progNewbie Obywatel (1,130 p.)

@Chess, Hej, czy mógłbyś ocenić logikę przy połączeniu między skryptem, a SQL'em i czy to co chce zrobić ma prawo działać, a może można coś lepiej zrobić.

------------------------------------------------------------------------------------------------

Baza danych:

Tabela "users":

idUsera | stanowisko  gdzie za przykład weźmy

idUsera = 1  stanowisko = lekarz , 

idUsera = 2  stanowisko = k_medyczny

Tabela "procedures":

idProcedure | nameProc | descProc | typeProc

Tabela "connections":

idConnection | idUsera | idProcedure

Dodatkowe informacje:

Users są przeze mnie wcześniej odręcznie uzupełnione, reszta ma się automatycznie uzupełniać.

-----------------------------------------------------------------------------------------------

Z kodu HTML proszę o skupienie się tylko nad tablicą medyczne[]

<input type="checkbox" id="expand_list_select1"/>
	<input type="checkbox" id="expand_list_select2"/>
	<form method="post">
		<div id="field_adding_informations">
			Nazwa procedury:<br>
			<input type="text" name="add_name_procedure" placeholder="Nazwa..." /><br><br>
			Opis procedury:<br>
			<textarea name="add_desc_procedure" placeholder="Opis procedury..."></textarea><br>
			Typ procedury:<br>
			<select name="add_type_procedure">
				<option value="medyczne">Medyczne</option>
				<option value="finansowe">Finansowe</option>
				<option value="obslugowe">Obsługowe</option>
			</select>
		</div>
		<div id="field_btn_choose_position">
			<button class="display_btn" type="button"><label for="expand_list_select1">Medyczne</label></button>
			<button class="display_btn" type="button"><label for="expand_list_select2">Obsługowe</label></button>
		</div>
		<div id="field_display_position">
			<select name="medyczne[]" multiple="multiple" class="sel1">
				<option value="lekarz">Lekarze</option>
				<option value="k_medyczny">Kierownik Medyczny</option>
				<option value="piel_koordy">Pielęgniarka Koordynująca</option>
				<option value="technik">Technicy</option>
				<option value="pielegniarka">Pielęgniarki</option>
			</select>
			<select name="obslugowe[]" multiple="multiple" class="sel2">
				<option value="recepcja">Recepcja</option>
				<option value="k_oddzialu">Kierownik Oddziału</option>
				<option value="k_administracyjny">Kierownik Administracyjny</option>
				<option value="koordy_recepcji">Koordynator Recepcji</option>
				<option value="crw">Koordynator CRW</option>
			</select>
		</div><br>
		<div id="submit">
			<br><br>
			<input type="submit" name="add_submit_procedure" value="Opublikuj"/>
		</div>
	</form>

Skrypt PHP, niedokończony bo mam problem z zapytaniem SQL.

if(isset($_POST['add_submit_procedure'])){
		$name_procedure = $_POST['add_name_procedure'];
		$desc_procedure = $_POST['add_desc_procedure'];
		$type_procedure = $_POST['add_type_procedure'];
		$connection = new mysqli('localhost', 'root', '', 'projekt_cmp');
		$sql_add_med_infos = "INSERT INTO procedures VALUES (NULL, '$name_procedure', '$desc_procedure', '$type_procedure')";
		$conenction->query($sql_add_med_infos);
		if(isset($_POST['medyczne'])){
			$medyczneArray = $_POST['medyczne'];
			foreach($medyczneArray as $key => $value){
				
			}
		}
	}

-----------------------------------------------------------------------------------------------------------

A teraz logika i to co chciałbym uzyskać:

1. Pierwsze zapytanie SQL  $sql_add_med_infos dodaje nową procedurę do tabeli "procedures"

2. Jeśli zostało przywołane pole select = medyczne[] to tworzę tablicę $medyczneArray, która przetrzymuje te optiony, które zostały zaznaczone przez usera.

Następnie w pętli foreach dla każdego wybranego optiona:

a) chcę złapać za idUsera gdzie $value = users.stanowisko, czyli w pierwszym przypadku łapiemy za to idUsera gdzie lekarz = lekarz, czyli łapiemy za idUsera = 1.(Zakładamy że takiego optiona właśnie zaznaczył user.)

b) łapię za idProcedure gdzie $_POST['name_procedure'] = procedures.nameProc, czyli za to gdzie nazwa procedury wpisana do formularza jest taka sama jak taka jak w bazie danych. (tę procedurę dodaliśmy własnie w pierwszym zapytaniu SQL w naszym skrypcie)

c) Tworzę zapytanie, które tworzy tyle połączeń w tabeli $connection ile zostało zaznaczonych optionów. 

---------------------------------------------------------

Opierając się więc już na żywym przykładzie:

Klikam przycisk "medyczne" i pojawia się select medyczne[] gdzie mamy 5 możliwości, optionów.

Zaznaczam 2 pierwsze czyli: lekarz, k_medyczny.

Pola formularza typu: Nazwa, opis, typ procedury dodajemy do tabeli "procedures".

Teraz dla wybranego optiona = lekarz. 

Sprawdzam w bazie danych że option = lekarz jest wpisany w bazie danych jako idUsera = 1.

Teraz chcę wydobyć idProcedure czyli przyrównuję nazwę z formularza z nazwą procedury w bazie danych i w ten sposób wydobywam odpowiednie ID.

Na koniec w tabeli "connections": 

Tworzy się nowy wiersz gdzie:

idConnection = 1

idUsera = 1

idProcedure = 1

-------------------------

idConnection = 2

idUsera = 2

idProcedure = 1

 

Czyli dla wielu stanowisk chcę przypisać jedną procedurę w bazie danych.

Czy ten sposób jaki opisałem jest logiczny i możliwy do wykonania, męczę się z tym ostatnim zapytaniem obsługującym to dodawanie do tabeli "connections"

 

 

 

 

 

komentarz 20 listopada 2018 przez progNewbie Obywatel (1,130 p.)

Dobra, nie wziąłem pod uwagę tego, że na etapie dodawania tych procedur do bazy danych nie ma potrzeba tworzenia relacji pomiędzy tabelami, ważne że nazwy kolumn są dobre, a relacje mogę tworzyć dopiero przy wyciąganiu danych z bazy danych, gdzie będzie o wiele prościej bo będzie działać klauzula WHERE.

Wrzucam swój kod, może znowu uda się rzucić jakieś pro tip'y. :)

	if(isset($_POST['submit'])){
		$add_name = $_POST['add_name'];
		$add_desc = $_POST['add_desc'];
		$add_type = $_POST['add_type'];
		$connection = new mysqli('localhost', 'root', '', 'projekt_cmp');
		$sql1 = "INSERT INTO procedures VALUES (NULL, '$add_name', '$add_desc', '$add_type')";
		$connection->query($sql1);
		
		$sql3 = "SELECT idProcedure from procedures WHERE nameProcedure = '$add_name'";
		$result2 = $connection->query($sql3);
		$row2 = $result2->fetch_assoc();
		$idprocedure = $row2['idProcedure'];
		
		$medArray = $_POST['medyczne'];
		foreach($medArray as $key => $value){
				$sql2 = "SELECT idUsera FROM users WHERE stanowisko = '$value'";
				$result1 = $connection->query($sql2);
				$row1 = $result1->fetch_assoc();
				$idusera = $row1['idUsera'];
				
				$sql4 = "INSERT INTO connections VALUES (NULL, '$idusera', '$idprocedure')";
				$connection->query($sql4);
		}
			
	}

Co tu robię: 

Przypisuję dane z pól z formularza do zmiennych.

Dodaję nową procedurę do tabeli procedures

Teraz Selectem wyciągam ID tej nowo utworzonej procedury

W pętli foreach wydobywam ID usera

Dodaję w tabeli "connections" nowe połączenia. między użytkownik/procedura używając ID, aby później w wypluwaniu tych procedur móc tworzyć relacje.

komentarz 20 listopada 2018 przez Chess Szeryf (76,710 p.)
edycja 20 listopada 2018 przez Chess
<form method="get" action="http://127.0.0.1:8000/forumpasja_informatyki/dbdb.php/">

	<select name="trees[]" multiple="multiple">
		<option value="oak">oak</option>
		<option value="spruce">spruce</option>
		<option value="hazel">hazel</option>
		<option value="pine">pine</option>
		<option value="beech">beech</option>
	</select>
	
	<input type="submit" name="iss" value="add_records_to_tree_with_color"/>
</form>

<form method="get" action="http://127.0.0.1:8000/forumpasja_informatyki/dbdb.php/">
	<input type="submit" name="iss2" value="add_record_to_trees2"/>
</form>
<?php
$db_conn = new mysqli('127.0.0.1', 'root', 'mystrongpass', 'rr');

function check_returns_values(&...$arg_arr) {
	
	$collecter = [];
	
	foreach($arg_arr as $arg_value) {
		$collecter[] = $arg_value ?? false;
	}
	
	return $collecter;
	
}

$array_issets = check_returns_values($_GET['iss'], $_GET['trees'], $_GET['iss2'], $c1, $c2, $c3, $_GET['iss3_fill'],$_GET['added_row'],$_GET['added_rows']);

$c1 = 'green';
$c2 = 'yellow';
$c3 = 'orange';

if($array_issets[2]) {

	$adding_color_leaves = "INSERT INTO trees2 VALUES (null, '$c1', '$c2', '$c3');";
	var_dump($db_conn->query($adding_color_leaves));
	
	header('Location: http://127.0.0.1:8000/forumpasja_informatyki/dbdb.php/?added_row='.$db_conn->affected_rows);
}

$choose_color = "SELECT id FROM trees2 WHERE trees2.kind = '$c1';";

if(($choose_color_ex = $db_conn->query($choose_color)) && !empty($c1)) {
	
	while($collecter[] = $choose_color_ex->fetch_assoc()['id']);

}

echo "<br /><br />";
	
if($array_issets[0] && !empty($array_issets[1])) {
   $choose_tree = '';
		
   $flag = true;
		
   foreach($array_issets[1] as $tree) {
      if($flag === true) {
         $choose_tree = "SELECT id FROM trees WHERE trees.kind = '$tree'";
	     $flag = false;
      } else {
         $choose_tree .= " OR trees.kind = '$tree'";
      }
   }

   $choose_tree_ex = $db_conn->query($choose_tree);

   while($find_kind_tree[] = $choose_tree_ex->fetch_assoc()['id']);

   $added_rows = 0;

   for($i=0;$i<count($collecter);$i++) {
      $insert_color = "INSERT INTO tree_with_color VALUES (null, $collecter[$i], $collecter[$i]);";
         if((in_array(($collecter[$i]), ($find_kind_tree))) && $insert_color_ex=$db_conn->query($insert_color)) {
            $added_rows++;
         }
   }

   header('Location: http://127.0.0.1:8000/forumpasja_informatyki/dbdb.php/?added_rows='.$added_rows);
		
}

echo 'Added '.((int)$_GET['added_rows']).' row(s) to table tree_with_color.'.PHP_EOL;
echo 'Added '.((int)$_GET['added_row']).' row(s) to table trees2.'.PHP_EOL;
?>
show create table tree_with_color\G
*************************** 1. row ***************************
       Table: tree_with_color
Create Table: CREATE TABLE `tree_with_color` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `id1` int(11) DEFAULT NULL,
  `id2` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=193 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
show create table trees\G
*************************** 1. row ***************************
       Table: trees
Create Table: CREATE TABLE `trees` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `kind` varchar(20) DEFAULT NULL,
  `description` varchar(20) DEFAULT NULL,
  `third` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
show create table trees2\G
*************************** 1. row ***************************
       Table: trees2
Create Table: CREATE TABLE `trees2` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `kind` varchar(20) DEFAULT NULL,
  `description` varchar(20) DEFAULT NULL,
  `third` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=71 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

Staraj się "płasko" pisać aplikację, bez piramidy if'ów, itd.. Rozbij ten kod na kilka formularzy, jeśli to było Twoim zamysłem.  Dodanie empty, itd. zostawiam Tobie oraz jak chcesz, to też zamienienie header na coś innego, żeby po reload'zie nie wysyłało drugi raz formularza (F5, refresh, ctrl+R, ctrl+F5, itd.). Jest to tzw. ponowne przesłanie wartości z tablicy superglobal'nej po odświeżeniu strony. Zamienienie ścieżek w header (jeśli chciałbyś to zostawić) na automatyczne (żeby skrypt sam je z URL ściągnął) też zostawiam. A jak to wykonać, opisane jest np. tutaj. Możesz zmienić method z POST na GET, żeby nie można było zmienić jawnie (w łatwy sposób) wartości, ponieważ teraz można zmienić i może zostać wypisane np. po modyfikacji i refresh'u, to: "Added 5 row(s) to table...", itp.. A byłoby to nieprawdą. 

Zazwyczaj stosuj (bardziej) elastyczne rozwiązania (solutions) do dalszej rozbudowy aplikacji. Dzięki tej pierwszej funkcji nie musisz pisać ciągle isset, by sprawdzić wartości z formularza. 

Czy rozwiązanie, które zaprezentowałeś jest logiczne, to już musisz przemyśleć sam, zauważ, że to się powtarza te id w tabeli connections u Ciebie i u mnie tree_with_color.

Odstąpiłeś od głównego nurtu tematu. Jeśli chcesz zadać kolejne pytanie, załóż nowy wątek. Trochę taki offtop się zrobił, początkowe pytanie było o coś innego. Jeśli chcesz, to odpisz na ten komentarz, ale nie zadawaj już pytań w tym temacie, ponieważ następne pytania (post'y) mogą być raportowane do moderatora. Możesz zadać pytanie/pytania odnośnie tego komentarza i dopytać o niektóre zagwozdki na temat kodu i rozwiązania, ale nie zaczynaj zadawać pytań odbiegających od tej ostatniej wypowiedzi swojej i mojej. Pytanie, które zadałeś powinno być w nowym wątku, no ale cóż zadałeś w tym samym ....

Podobne pytania

0 głosów
1 odpowiedź 140 wizyt
pytanie zadane 23 maja 2017 w C# przez sharkus101 Początkujący (330 p.)
0 głosów
5 odpowiedzi 663 wizyt
pytanie zadane 17 grudnia 2018 w PHP przez jared Gaduła (3,600 p.)
0 głosów
1 odpowiedź 432 wizyt
pytanie zadane 7 listopada 2017 w PHP przez borygo Nowicjusz (160 p.)

92,556 zapytań

141,404 odpowiedzi

319,562 komentarzy

61,942 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...