Når du skriver en artikel på din blog, bliver du ofte nødt til at vise billeder mellem tekster, normalt til illustrationsformål. CKEditor hjælper dig med at opnå dette, men det kan være lidt vanskeligt eller svært at arbejde med, hvis du ikke bruger et plugin. Årsagen er, at CKEditor kun accepterer webadressen på billedet, der skal indsættes i indlægsteksten, og billedet skal allerede eksistere på internettet og ikke på din lokale maskine.
Det, vi skal gøre nu, er at finde en måde at få billedet uploadet til en billedmappe i vores projekt, mens vi stadig skriver indlægget. når billedet er blevet uploadet, vil URL'en på billedet blive sendt tilbage, som vi derefter kan bruge i vores CKEditor.
Det første er, at vi tilføjer en knap, som, når der klikkes på den, gennemser brugerens lokale computer efter billeder (på samme måde som et klik på et -element ville gøre). Når brugeren har valgt et billede, uploades billedet øjeblikkeligt i baggrunden ved hjælp af Ajax (uden at genindlæse siden) i en onChange-begivenhed, og URL'en for det pågældende billede returneres fra serveren. Den returnerede URL vises i en pop-up modal, som bliver kopieret til udklipsholderen, når brugeren klikker på den. Brugeren kan nu klikke på billedikonet på CKEditor og indsætte URL'en til billedet i det.
Lad os implementere dette på et miniprojekt og se, hvordan det fungerer.
Opret en mappe kaldet ckeditor-images og inde i denne mappe, opret en undermappe kaldet images, og 4 filer, nemlig:index.php, server.php, scripts.js og main.css.
Billedmappen vil indeholde billederne uploadet fra vores CKEditor.
Åbn index.php op og indsæt følgende kode i den.
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>
Som du kan se, har vi tilføjet bootstrap CSS og JS gennem CDN. Vi tilføjede også JQuery, fordi vi vil uploade billederne ved hjælp af Ajax-opkald. Til sidst tilføjede vi CKEditor plugin-koden, som vi stadig skal initialisere på vores tekstområde i formularen. scripts.js er hvor JQuery-scriptet vil ligge.
Lige efter postformularen tilføjede vi noget kode til pop-up modal med id sat til id="myModal". Denne modal bliver ikke brugt nu, men når billedet er blevet uploadet, vil den returnerede URL for billedet blive vist på denne modal. Så glem det for nu.
Hvis du går til http://localhost/ckeditor-images/index.php, vil du se det statiske indlæg og formularen. Åbn main.css, og lad os tilføje et par stile til denne side.
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;
}
Åbn scripts.js og tilføj denne kode i den:
scripts.js:
// initialize ckeditor
CKEDITOR.replace('body');
Opdater siden, og du vil bemærke nogle ændringer i stilen såvel som det tekstområde, der nu er vores CKEditor, der er fyldt med mange ikoner.
Opret en database kaldet ckeditor-images. I denne database skal du oprette en tabel kaldet posts med felter:
- id - INT(11)
- titel - VARCHAR(255)
- body - VARCHAR(255)
Indsæt nu et eller flere dummy-indlæg i indlægstabellen, så vi kan forespørge på det og vise det på siden.
Opretter forbindelse til databasen
Åbn server.php op og indtast denne kode i den:
<?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);
?>
Denne kode henter de indlæg, der er i databasen, til en $posts-variabel. Denne variabel gøres tilgængelig i vores index.php-fil af include-sætningen på den første kodelinje i index.php -- linjen der inkluderer server.php-filen inde i index.php.
I index.php-filen skal du fjerne hele div-elementet, der har attributten class="post" og erstatte det med denne kode:
// ... 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
Som du kan se, fører hvert indlæg, når der klikkes på dets titel, til details.php overførte id'et for indlægget til det. Opret en fil med navnet details.php og indsæt denne kode i den:
details.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>
I den øverste sektion forbinder vi til databasen, griber post-id'et, der blev sendt fra index.php-siden, og forespørger på det pågældende indlæg. Indlægget gemmes derefter i $post-variablen, som derefter vises på siden.
Nu kan vi begynde at kode dynamikken ved faktisk at uploade billedet i CKEditor. Åbn scripts.js og erstat alt indeni med dette:
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);
}
});
});
});
});
Følg kommentarerne i denne kode, og du vil forstå trinene. Først klikker brugeren på knappen "upload billede". Dette udløser en klikhændelse på filinputtet, hvis visning er indstillet til ingen. Når brugeren vælger et billede fra deres lokale computer, udløses en onChange-hændelse på filinputtet, og det er her, vi uploader billedet ved hjælp af Ajax.
På dette tidspunkt bliver vores billede allerede sendt til serveren i en Ajax-anmodning. Men indtil videre i vores server.php har vi kun oprettet forbindelse til databasen. Vi har endnu ikke skrevet koden til at modtage billedet fra Ajax-anmodningen og uploade det til billedmappen. Lad os gøre det nu.
Åbn server.php-filen igen og tilføj denne kode til den:
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();
}
}
Denne kode accepterer Ajax-anmodningen, der følger med billedet, uploader billedet til billedmappen og returnerer en fuldt kvalificeret URL til billedet. Husk, at på dette tidspunkt er brugeren stadig travlt med at skrive sit indlæg på formularen til oprettelse af indlæg, og alt dette sker i baggrunden.
Webadressen, der er blevet returneret fra serveren, vises derefter på en pop-up-modal, som dukker op, så brugeren kan kopiere webadressen. Når modalen dukker op, og brugeren klikker på den viste URL, bliver den kopieret til udklipsholderen, og brugeren kan fortsætte med at bruge denne billed-URL i CKEditor ved at indsætte denne URL på det rigtige sted.
Vi er stort set færdige med kernekonceptet i denne tutorial. Hvornår er tilbage nu, er for os at trykke på send for at vores indlæg sendes til serveren og gemmes i databasen. For at gøre det berører vi kun én fil.
Åbn server.php og tilføj denne kode i slutningen af filen:
// ... 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");
}
Og det bringer os til slutningen af denne tutorial. Jeg håber, at du godt forstod vores mål i dette selvstudie, og hvordan vi har løst det.
Et nærmere kig
På dette tidspunkt ser alt ud til at fungere fint. Vi uploader et billede og bruger dets URL i vores CKEditor helt okay, men hvor effektivt er dette system. Lad os sige, at du begynder at skrive et indlæg og undervejs føler dig udmattet efter at have uploadet et par billeder, hvordan fortryder du uploads. Hvordan frigør du plads på din server? En løsning jeg vil foreslå er, at du opretter en billedtabel i databasen, der kun tager postID'et og navnet på billedet. Hver gang du uploader et billede, gemmer du billednavnet i billedtabellen med null som postID. Hvis du ændrer mening og ikke gemmer indlægget til sidst, forbliver nulpunktet i billedtabellen. Derefter kan du skrive et script, som vil forespørge på alle databasebilleder, der har null som deres tilknyttede postID'er. Udfordr dig selv med dette og kode det. Hvis du støder på problemer, så læg det i kommentarerne nedenfor, og hjælpen vil komme.
Som altid, tak for din tid. Håber du finder dette nyttigt. Hvis du kunne lide dette indlæg, så tjek venligst mine andre tutorials og del og anbefal mit websted med dine venner.
Med venlig hilsen!