sql >> Databáze >  >> RDS >> Mysql

Nahrávání obrázků v CKEditoru bez použití pluginu

Při psaní článku na svůj blog budete často muset mezi texty zobrazovat obrázky, obvykle pro ilustrační účely. CKEditor vám toho pomůže dosáhnout, ale pokud nepoužíváte plugin, může to být trochu složité nebo obtížné s ním pracovat. Důvodem je, že CKEditor přijímá pouze URL obrázku , který má být vložen do textu příspěvku, a obrázek již musí existovat na internetu, nikoli na vašem místním počítači.

Nyní musíme najít způsob, jak nahrát obrázek do adresáře obrázků v našem projektu, zatímco stále píšeme příspěvek; jakmile bude obrázek nahrán, URL obrázku bude zasláno zpět, které pak můžeme použít v našem CKEditoru.

První věcí je, že přidáme tlačítko, které po kliknutí vyhledá obrázky v místním počítači uživatele (stejným způsobem, jako by to udělalo kliknutí na prvek ). Jakmile uživatel vybere obrázek, je tento obrázek okamžitě nahrán na pozadí pomocí Ajaxu (bez opětovného načítání stránky) v události onChange a ze serveru je vrácena adresa URL tohoto konkrétního obrázku. Vrácená adresa URL se zobrazí ve vyskakovacím okně, které se zkopíruje do schránky, když na ni uživatel klikne. Uživatel nyní může kliknout na ikonu obrázku v CKEditoru a vložit do ní adresu URL obrázku.

Pojďme to implementovat na miniprojekt a uvidíme, jak to funguje.

Vytvořte složku nazvanou ckeditor-images a v této složce vytvořte podsložku s názvem images a 4 soubory jmenovitě:index.php, server.php, scripts.js a main.css.

Složka obrázků bude obsahovat obrázky nahrané z našeho CKEditoru.

Otevřete index.php a umístěte do něj následující kód.

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">&times;</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>

Jak můžete vidět, přidali jsme bootstrap CSS a JS přes CDN. Přidali jsme také JQuery, protože obrázky budeme nahrávat pomocí volání Ajax. Nakonec jsme přidali kód pluginu CKEditor, který ještě musíme inicializovat v naší textové oblasti ve formuláři. scripts.js je místo, kde bude umístěn skript JQuery.

Hned za formulář příspěvku jsme přidali nějaký kód pro vyskakovací modal s id nastaveným na id="myModal". Tento modal se nyní nepoužívá, ale po nahrání obrázku se na tomto modu zobrazí vrácená adresa URL obrázku. Takže na to prozatím zapomeňte.

Pokud přejdete na http://localhost/ckeditor-images/index.php, uvidíte zobrazený statický příspěvek a formulář. Otevřete main.css a přidejte na tuto stránku několik stylů.

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;
}

Otevřete skript scripts.js a přidejte do něj tento kód:

scripts.js:

// initialize ckeditor
CKEDITOR.replace('body');

Obnovte stránku a všimnete si nějaké změny ve stylu a také v textové oblasti, která je nyní naším CKEditorem nabitá mnoha ikonami.

Vytvořte databázi s názvem ckeditor-images. V této databázi vytvořte tabulku nazvanou příspěvky s poli:

  • id – INT(11)
  • název – VARCHAR(255)
  • tělo – VARCHAR(255)

Nyní vložte jeden nebo více fiktivních příspěvků do tabulky příspěvků, abychom je mohli vyhledat a zobrazit na stránce.

Připojování k databázi

Otevřete server.php a zadejte do něj tento kód:

<?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);
?>

Tento kód načte příspěvky, které jsou v databázi, do proměnné $posts. Tato proměnná je zpřístupněna v našem souboru index.php příkazem include na prvním řádku kódu v index.php -- řádku, který obsahuje soubor server.php uvnitř index.php.

V souboru index.php odstraňte celý prvek div, který má atribut class="post" a nahraďte jej tímto kódem:

// ... 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

Jak můžete vidět, každý příspěvek po kliknutí na jeho název vede k tomu, že mu soubor details.php předá ID příspěvku. Vytvořte soubor s názvem details.php a vložte do něj tento kód:

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>

V horní části se připojíme k databázi, vezmeme ID příspěvku, které bylo odesláno ze stránky index.php a dotazujeme se na konkrétní příspěvek. Příspěvek se poté uloží do proměnné $post, která se poté zobrazí na stránce.

Nyní můžeme začít kódovat dynamiku skutečného nahrávání obrázku do CKEditoru. Otevřete skript scripts.js a nahraďte vše uvnitř tímto:

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);
				}
			});
		});

	});
});

Postupujte podle komentářů v tomto kódu a pochopíte kroky. Nejprve uživatel klikne na tlačítko „nahrát obrázek“. To spustí událost kliknutí na vstupu souboru, jehož zobrazení bylo nastaveno na žádné. Jakmile uživatel vybere obrázek ze svého místního počítače, na vstupu souboru se spustí událost onChange a zde obrázek nahrajeme pomocí Ajaxu.

V tuto chvíli je náš obrázek již odesílán na server v požadavku Ajax. Ale v našem serveru.php jsme se zatím připojili pouze k databázi. Ještě jsme nenapsali kód pro přijetí obrázku z požadavku Ajax a jeho nahrání do složky obrázků. Udělejme to teď.

Otevřete soubor server.php ještě jednou a přidejte do něj tento kód:

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();
  	}
}

Tento kód přijme požadavek Ajax, který je dodáván s obrázkem, nahraje obrázek do složky obrázků a vrátí obrázku plně kvalifikovanou adresu URL. Pamatujte, že v tuto chvíli je uživatel stále zaneprázdněn psaním svého příspěvku do formuláře pro vytvoření příspěvku a to vše se děje na pozadí.

Adresa URL, která byla vrácena ze serveru, se poté zobrazí ve vyskakovacím okně, které se uživateli zobrazí, aby si adresu URL zkopíroval. Když se modal objeví a uživatel klikne na zobrazenou adresu URL, zkopíruje se do schránky a uživatel může pokračovat v používání této adresy URL obrázku v CKEditoru vložením této adresy URL na příslušné místo.

Se základním konceptem tohoto tutoriálu jsme téměř hotovi. Nyní zbývá stisknout Odeslat, aby byl náš příspěvek odeslán na server a uložen do databáze. K tomu se dotkneme pouze jednoho souboru.

Otevřete server.php a přidejte tento kód na konec souboru:

// ... 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");
}

A tím se dostáváme na konec tohoto návodu. Doufám, že jste dobře pochopili náš cíl v tomto tutoriálu a to, jak jsme jej řešili.

 Podrobnější pohled

V tuto chvíli se zdá, že vše funguje dobře. Nahráváme obrázek a používáme jeho URL v našem CKEditoru celkem v pořádku, ale jak efektivní je tento systém. Řekněme, že začnete psát příspěvek a cestou se cítíte vyčerpaní poté, co jste nahráli několik obrázků, jak nahrávání zrušíte. Jak uvolníte místo na serveru? Řešením, které bych navrhl, je vytvořit v databázi tabulku obrázků, která přebírá pouze postID a název obrázku. Pokaždé, když nahrajete obrázek, uložíte název obrázku do tabulky obrázků s hodnotou null jako postID. Pokud si to rozmyslíte a příspěvek nakonec neuložíte, v tabulce obrázků zůstane nula. Potom můžete napsat skript, který se bude dotazovat na všechny databázové obrázky, které mají null jako svá přidružená postID. Vyzvěte se s tím a nakódujte to. Pokud narazíte na nějaké potíže, zanechte je v komentářích níže a pomoc přijde.

Jako vždy děkuji za váš čas. Doufám, že vám to pomůže. Pokud se vám tento příspěvek líbil, podívejte se prosím na mé další návody a sdílejte a doporučujte mé stránky svým přátelům.

S pozdravem!


  1. Magicbricks migruje na MariaDB, aby podpořila svůj velkoobjemový provoz

  2. Porovnání řetězců s rozlišením velkých a malých písmen

  3. Demystifikování typů čekání CXPACKET a CXCONSUMER v SQL Server

  4. MySQL - UPDATE více řádků s různými hodnotami v jednom dotazu