Estoy tratando de desarrollar un sitio web de preguntas y respuestas en PHP usando una base de datos PostgreSQL. Tengo una acción para crear una página que tiene un título, cuerpo, categoría y etiquetas. Logré insertar todos esos campos, sin embargo, tengo algunos problemas al insertar múltiples valores de etiqueta.
Utilicé esta función para obtener los valores separados por comas en una matriz y ahora quiero algo que inserte cada elemento de la matriz en la base de datos (evitando repeticiones) en las tags de la tabla y luego inserte en mis muchas etiquetas de questiontags de la tabla de relaciones:
$tags = explode(',', $_POST['tags']); //Comma separated values to an arrayque imprime algo como esto:
Array ( [0] => hello [1] => there [2] => this [3] => is [4] => a [5] => test )acción/crear_pregunta.php
$category = get_categoryID_by_name($_POST['category']); $question = [ 'userid' => auth_user('userid'), 'body' => $_POST['editor1'], 'title' => $_POST['title'], 'categoryid' => $category ]; create_question($question, $tags); y luego mi create_question donde debo insertar las etiquetas.
function create_question($question, $tags) { global $conn; $query_publications=$conn->prepare("SELECT * FROM insert_into_questions(:body, :userid, :title, :categoryid); "); $query_publications->execute($question); }Estaba pensando en hacer algo como esto:
conexión global $;
foreach ($tags as $tag) { $query_publications=$conn->prepare("INSERT INTO tags(name) VALUES($tag); "); $query_publications->execute($question); } Pero luego necesitaría la identificación de las etiquetas para insertar en mi tabla muchos a muchos. ¿Necesito crear otro procedimiento, get_tags_id y luego obtener una matriz tag_id e insertarlos como intenté con las etiquetas? ¿Cuándo ejecuto la consulta? ¿Después de ambos insertos o uno al final del otro?
Perdón por cualquier término mal usado o por mi pregunta de novato. Soy nuevo en PHP y estoy luchando con algunos conceptos nuevos.
Puede hacerlo todo en un comando SQL usando CTE.
Suponiendo que Postgres 9.6 y este esquema clásico de muchos a muchos (ya que no lo proporcionó):
CREATE TABLE questions ( question_id serial PRIMARY KEY , title text NOT NULL , body text , userid int , categoryid int ); CREATE TABLE tags ( tag_id serial PRIMARY KEY , tag text NOT NULL UNIQUE); CREATE TABLE questiontags ( question_id int REFERENCES questions , tag_id int REFERENCES tags , PRIMARY KEY(question_id, tag_id) );Para insertar una sola pregunta con una serie de etiquetas :
WITH input_data(body, userid, title, categoryid, tags) AS ( VALUES (:title, :body, :userid, :tags) ) , input_tags AS ( -- fold duplicates SELECT DISTINCT tag FROM input_data, unnest(tags::text[]) tag ) , q AS ( -- insert question INSERT INTO questions (body, userid, title, categoryid) SELECT body, userid, title, categoryid FROM input_data RETURNING question_id ) , t AS ( -- insert tags INSERT INTO tags (tag) TABLE input_tags -- short for: SELECT * FROM input_tags ON CONFLICT (tag) DO NOTHING -- only new tags RETURNING tag_id ) INSERT INTO questiontags (question_id, tag_id) SELECT q.question_id, t.tag_id FROM q, ( SELECT tag_id FROM t -- newly inserted UNION ALL SELECT tag_id FROM input_tags JOIN tags USING (tag) -- pre-existing ) t;dbfiddle aquí
Esto crea cualquier etiqueta que aún no exista sobre la marcha.
La representación de texto de una matriz de Postgres se ve así: {tag1, tag2, tag3} .
Si se garantiza que la matriz de entrada tiene etiquetas distintas, puede eliminar DISTINCT de CTE input_tags .
Explicación detallada:
Si tiene escrituras simultáneas , es posible que deba hacer más. Considere el segundo enlace en particular.