Quando scrivi un articolo sul tuo blog, dovrai spesso visualizzare immagini tra i testi di solito a scopo illustrativo. CKEditor ti aiuta a raggiungere questo obiettivo, ma può essere un po' complicato o difficile da lavorare se non stai usando un plugin. Il motivo è che CKEditor accetta solo l'URL dell'immagine da inserire nel testo del post e l'immagine deve già esistere su Internet e non sul computer locale.
Quello che dobbiamo fare ora è trovare un modo per caricare l'immagine in una directory di immagini nel nostro progetto mentre stiamo ancora scrivendo il post; una volta che l'immagine è stata caricata, verrà rispedito l'URL dell'immagine che possiamo quindi utilizzare nel nostro CKEditor.
La prima cosa è che aggiungeremo un pulsante che, una volta cliccato, cerca le immagini nel computer locale dell'utente (nello stesso modo in cui farebbe un clic su un elemento ). Una volta che l'utente seleziona un'immagine, tale immagine viene immediatamente caricata in background utilizzando Ajax (senza ricaricare la pagina) in un evento onChange e l'URL di quella particolare immagine viene restituito dal server. L'URL restituito viene visualizzato in un pop-up modale che viene copiato negli appunti quando l'utente fa clic su di esso. L'utente può ora fare clic sull'icona dell'immagine su CKEditor e incollarvi l'URL dell'immagine.
Implementiamolo su un mini-progetto e vediamo come funziona.
Crea una cartella chiamata ckeditor-images e all'interno di questa cartella, crea una sottocartella chiamata immagini e 4 file ovvero:index.php, server.php, scripts.js e main.css.
La cartella delle immagini conterrà le immagini caricate dal nostro CKEditor.
Apri index.php e inserisci il seguente codice.
index.php:
<?php include('server.php') ?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Uploading images in CKEditor using PHP</title>
<!-- Bootstra CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" />
<!-- Custom styling -->
<link rel="stylesheet" href="main.css">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2 post-div">
<!-- Display a list of posts from database -->
<?php foreach ($posts as $post): ?>
<div class="post">
<h3>
<a href="details.php?id=<?php echo $post['id'] ?>"><?php echo $post['title']; ?></a>
</h3>
<p>
<?php echo html_entity_decode(preg_replace('/\s+?(\S+)?$/', '', substr($post["body"], 0, 200))); ?>
</p>
</div>
<?php endforeach ?>
<!-- Form to create posts -->
<form action="index.php" method="post" enctype="multipart/form-data" class="post-form">
<h1 class="text-center">Add Blog Post</h1>
<div class="form-group">
<label for="title">Title</label>
<input type="text" name="title" class="form-control" >
</div>
<div class="form-group" style="position: relative;">
<label for="post">Body</label>
<!-- Upload image button -->
<a href="#" class="btn btn-xs btn-default pull-right upload-img-btn" data-toggle="modal" data-target="#myModal">upload image</a>
<!-- Input to browse your machine and select image to upload -->
<input type="file" id="image-input" style="display: none;">
<textarea name="body" id="body" class="form-control" cols="30" rows="5"></textarea>
</div>
<div class="form-group">
<button type="submit" name="save-post" class="btn btn-success pull-right">Save Post</button>
</div>
</form>
<!-- Pop-up Modal to display image URL -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">Click below to copy image url</h4>
</div>
<div class="modal-body">
<!-- returned image url will be displayed here -->
<input
type="text"
id="post_image_url"
onclick="return copyUrl()"
class="form-control"
>
<p id="feedback_msg" style="color: green; display: none;"><b>Image url copied to clipboard</b></p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- JQuery -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- Bootstrap JS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<!-- CKEditor -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/ckeditor/4.8.0/ckeditor.js"></script>
<!-- custom scripts -->
<script src="scripts.js"></script>
</body>
</html>
Come puoi vedere abbiamo aggiunto CSS e JS bootstrap tramite CDN. Abbiamo anche aggiunto JQuery perché caricheremo le immagini utilizzando le chiamate Ajax. Infine, abbiamo aggiunto il codice del plugin CKEditor che dobbiamo ancora inizializzare sulla nostra textarea nel form. scripts.js è dove risiederà lo script JQuery.
Subito dopo il modulo di posta, abbiamo aggiunto del codice per il modale pop-up con id impostato su id="myModal". Questo modale non viene utilizzato ora, ma quando l'immagine è stata caricata, l'URL restituito dell'immagine verrà visualizzato su questo modale. Quindi lascia perdere per ora.
Se vai su http://localhost/ckeditor-images/index.php, vedrai il post statico visualizzato e il modulo. Apri main.css e aggiungiamo alcuni stili a questa pagina.
main.css:
p {
font-size: 1.1em;
}
.post {
border: 1px solid #ccc;
padding: 10px;
margin-top: 15px;
}
.post h3 {
margin: 0px;
}
.post-div {
border: 1px solid #ccc;
margin-top: 30px;
margin-bottom: 30px;
padding: 20px;
}
.post-form {
margin-top: 80px;
}
/*DETAILS PAGE*/
.post-details p {
text-align: justify;
margin: 20px auto;
font-size: 1.2em;
}
.upload-img-btn {
position: absolute;
z-index: 9;
top: 35px;
right: 5px;
}
Apri scripts.js e aggiungi questo codice al suo interno:
scripts.js:
// initialize ckeditor
CKEDITOR.replace('body');
Aggiorna la pagina e noterai alcuni cambiamenti nello stile e nell'area di testo che ora è il nostro CKEditor caricato con molte icone.
Crea un database chiamato ckeditor-images. In questo database, crea una tabella chiamata post con campi:
- id - INT(11)
- titolo - VARCHAR(255)
- corpo - VARCHAR(255)
Ora inserisci uno o più post fittizi nella tabella dei post in modo che possiamo interrogarlo e visualizzarlo sulla pagina.
Connessione al database
Apri server.php e inserisci questo codice al suo interno:
<?php
// connect to database
$db = mysqli_connect("localhost", "root", "", "ckeditor-images");
// retrieve posts from database
$result = mysqli_query($db, "SELECT * FROM posts");
$posts = mysqli_fetch_all($result, MYSQLI_ASSOC);
?>
Questo codice recupera i post che si trovano nel database in una variabile $posts. Questa variabile è resa disponibile nel nostro file index.php dall'istruzione include nella prima riga di codice in index.php -- la riga che include il file server.php all'interno di index.php.
Nel file index.php, rimuovi l'intero elemento div che ha l'attributo class="post" e sostituiscilo con questo codice:
// ... more code here
<?php if (isset($posts)): ?>
<?php foreach ($posts as $post): ?>
<div class="post">
<h3>
<a href="details.php?id=<?php echo $post['id'] ?>"><?php echo $post['title'] ?></a>
</h3>
<p><?php echo $post['body']; ?></p>
</div>
<?php endforeach ?>
<?php else: ?>
<h2>No posts available</h2>
<?php endif ?>
// ... more code here
Come puoi vedere, ogni post quando si fa clic sul titolo, porta a details.php passandogli l'id del post. Crea un file chiamato dettagli.php e incollaci questo codice:
dettagli.php:
<?php
// connect to database
$db = mysqli_connect("localhost", "root", "", "ckeditor-images");
if (isset($_GET['id'])) {
$id = $_GET['id'];
$result = mysqli_query($db, "SELECT * FROM posts WHERE id=$id");
$post = mysqli_fetch_assoc($result);
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Uploading images in CKEditor using PHP</title>
<!-- Bootstra -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" />
<!-- Custom styling -->
<link rel="stylesheet" href="main.css">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2 post-div">
<div class="post-details">
<h2><?php echo $post['title'] ?></h2>
<p><?php echo html_entity_decode($post['body']); ?></p>
</div>
</div>
</div>
</div>
<!-- JQuery -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- Bootstrap JS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<!-- JQuery scripts -->
<script>
</script>
</body>
</html>
Nella sezione superiore, ci colleghiamo al database, prendiamo l'ID del post che è stato inviato dalla pagina index.php e interroghiamo quel particolare post. Il post viene quindi archiviato nella variabile $post che viene quindi visualizzata nella pagina.
Ora possiamo iniziare a codificare le dinamiche del caricamento effettivo dell'immagine nel CKEditor. Apri scripts.js e sostituisci tutto all'interno con questo:
scripts.js:
// initialize ckeditor
CKEDITOR.replace('body');
// Javascript function to copy image url to clipboard from modal
function copyUrl() {
var copyText = document.getElementById("post_image_url");
copyText.select();
document.execCommand("Copy");
// replace url with confirm message
$('#post_image_url').hide(1000);
$('#feedback_msg').show();
// hide modal after 2 seconds
setTimeout(function(){
$('#myModal').modal('hide');
$('#feedback_msg').hide();
$('#post_image_url').show();
}, 2000);
}
$(document).ready(function(){
// When user clicks the 'upload image' button
$('.upload-img-btn').on('click', function(){
// Add click event on the image upload input
// field when button is clicked
$('#image-input').click();
$(document).on('change', '#image-input', function(e){
// Get the selected image and all its properties
var image_file = document.getElementById('image-input').files[0];
// Initialize the image name
var image_name = image_file.name;
// determine the image extension and validate image
var image_extension = image_name.split('.').pop().toLowerCase();
if (jQuery.inArray(image_extension, ['gif', 'png', 'jpg', 'jpeg']) == -1) {
alert('That image type is not supported');
return;
}
// Get the image size. Validate size
var image_size = image_file.size;
if (image_size > 3000000) {
alert('The image size is too big');
return;
}
// Compile form values from the form to send to the server
// In this case, we are taking the image file which
// has key 'post_image' and value 'image_file'
var form_data = new FormData();
form_data.append('post_image', image_file);
form_data.append('uploading_file', 1);
// upload image to the server in an ajax call (without reloading the page)
$.ajax({
url: 'index.php',
method: 'POST',
data: form_data,
contentType: false,
cache: false,
processData: false,
beforeSend : function(){
},
success : function(data){
// how the pop up modal
$('#myModal').modal('show');
// the server returns a URL of the uploaded image
// show the URL on the popup modal
$('#post_image_url').val(data);
}
});
});
});
});
Segui i commenti in questo codice e capirai i passaggi. Innanzitutto, l'utente fa clic sul pulsante "carica immagine". Ciò attiva un evento di clic sull'input del file la cui visualizzazione è stata impostata su nessuno. Una volta che l'utente seleziona un'immagine dal proprio computer locale, viene attivato un evento onChange sull'input del file ed è qui che carichiamo l'immagine utilizzando Ajax.
A questo punto, la nostra immagine è già stata inviata al server in una richiesta Ajax. Ma finora nel nostro server.php ci siamo collegati solo al database. Non abbiamo ancora scritto il codice per ricevere l'immagine dalla richiesta Ajax e caricarla nella cartella delle immagini. Facciamolo ora.
Apri di nuovo il file server.php e aggiungi questo codice:
server.php:
// ... more code here ...
// if 'upload image' buttton is clicked
if (isset($_POST['uploading_file'])) {
// Get image name
$image = $_FILES['post_image']['name'];
// image file directory
$target = "images/" . basename($image);
if (move_uploaded_file($_FILES['post_image']['tmp_name'], $target)) {
echo "http://localhost/ckeditor-images/" . $target;
exit();
}else{
echo "Failed to upload image";
exit();
}
}
Questo codice accetta la richiesta Ajax fornita con l'immagine, carica l'immagine nella cartella delle immagini e restituisce un URL completo all'immagine. Ricorda che a questo punto l'utente è ancora impegnato a scrivere il proprio post nel modulo di creazione del post e tutto questo sta accadendo in background.
L'URL restituito dal server viene quindi visualizzato in un popup modale che viene visualizzato per consentire all'utente di copiare l'URL. Quando viene visualizzata la modale e l'utente fa clic sull'URL visualizzato, viene copiato negli appunti e l'utente può procedere a utilizzare l'URL di questa immagine in CKEditor incollando questo URL nella posizione appropriata.
Abbiamo praticamente finito con il concetto centrale di questo tutorial. Quando rimane ora, dobbiamo premere invia per inviare il nostro post al server e salvarlo nel database. Per fare ciò, toccheremo solo un file.
Apri server.php e aggiungi questo codice alla fine del file:
// ... more code here ...
// if form save button is clicked, save post in the database
if (isset($_POST['save-post'])) {
$title = mysqli_real_escape_string($db, $_POST['title']);
$body = htmlentities(mysqli_real_escape_string($db, $_POST['body']));
$sql = "INSERT INTO posts (title, body) VALUES ('$title', '$body')";
mysqli_query($db, $sql);
header("location: index.php");
}
E questo ci porta alla fine di questo tutorial. Spero che tu abbia compreso bene il nostro obiettivo in questo tutorial e come lo abbiamo affrontato.
Uno sguardo più da vicino
A questo punto tutto sembra funzionare bene. Stiamo caricando un'immagine e usando il suo URL nel nostro CKEditor abbastanza bene, ma quanto è efficiente questo sistema. Diciamo che inizi a scrivere un post e lungo la strada ti senti esausto dopo aver caricato alcune immagini, come annulli i caricamenti. Come si libera spazio sul server? Una soluzione che proporrei è quella di creare una tabella immagini nel database che prenda solo il postID e il nome dell'immagine. Ogni volta che carichi un'immagine, salvi il nome dell'immagine nella tabella delle immagini con null come postID. Se cambi idea e alla fine non salvi il post, il null rimane nella tabella delle immagini. Quindi puoi scrivere uno script che interrogherà tutte le immagini del database che hanno null come postID associati. Sfida te stesso con questo e codificalo. Se incontri qualche difficoltà, lasciala nei commenti qui sotto e arriverà l'aiuto.
Come sempre, grazie per il tuo tempo. Spero che ti sia d'aiuto. Se ti è piaciuto questo post, dai un'occhiata ai miei altri tutorial e condividi e consiglia il mio sito con i tuoi amici.
Cordiali saluti!