Integrating TinyMCE with Laravel

For those that do not know, I have used Laravel to create a custom content management system (CMS) for Linuxphile.  Laravel is a PHP framework that makes coding in PHP a dream.  Laravel and aritsan have rejevunated my lust for technology and very much my love of coding in PHP.  Alright, I'll stop cheesing about Laravel and get to the meat of this. 

When I set out to set things right (you remember, right, Linuxphile was hacked) I wanted to create, from the ground up, a CMS that would allow me full control, but still allow for ease of use.  To that end I knew from the beginning I'd be using some form of WYSIWYG editor.  These, typically javascript, editors just make posting new content to a website easier and faster.  My choices were really between CKEditor and TinyMCE, although I did go down the path of Nicedit too.  

TinyMCE is just that, tiny, but a full featured WYSIWYG editor and can be as bloated as you desire by enabling various plugins. For the most part the documentation is really straight forward.  I was able to get the file browser working within minutes, but the file upload feature required quite a bit more work.  Below are details one what I have done to get this working, with links to where I found pointers in the right direction. 

To begin let me state that I wrote this for Laravel 5, however, I was able to easily modify to exist with another website I created running Laravel 4.  So, for Laravel 5, there are really 3 files of import here.  

  • App\Http\routes.php
    • We'll need 2 routes here one for the file browswer and one for the image upload. 
 //file browser list 

Route::any('/imglist', ['as'=>'imglist', 'middleware'=>'auth', 'uses'=>'FileBrowserontroller@imageList']);
//Image upload

Route::any('/upload', ['middleware' => 'auth', 'uses' =>'FileBrowserontroller@index']);

  • App\Http\Controllers\FileBrowserController.php
    • This is where the magic happens so to speak.  We'll use the Storage class to get a list of files and return them in a JSON encoded response that is read by TinyMCE.
    public function imageList() {
            $imgList = array();
            $files = File::allfiles(public_path().'/img');
            foreach ($files as $file) {
                array_push($imgList, array("title"=>str_replace( './', '',$file), "value"=>'img/'.str_replace( './', '',$file)));
            }
            return json_encode($imgList);
        } 
    
    	public function upload(){
    	        $valid_exts = array('jpeg', 'jpg', 'png', 'gif'); // valid extensions
    	        $max_size = 2000 * 1024; // max file size (200kb)
    	        $path = public_path() . '/img/'; // upload directory
    	        $fileName = NULL;
    	        $file = Input::file('image');
    	        // get uploaded file extension
    	        //$ext = $file['extension'];
    	        $ext = $file->guessClientExtension();
    	        // get size
    	        $size = $file->getClientSize();
    	        // looking for format and size validity
    	        $name = $file->getClientOriginalName();
    	        if (in_array($ext, $valid_exts) AND $size < $max_size)
    	        {
    	            // move uploaded file from temp to uploads directory
    	            if ($file->move($path,$name))
    	            {
    	                $status = 'Image successfully uploaded!';
    	                $fileName = $name;
    	            }
    	            else {
    	                $status = 'Upload Fail: Unknown error occurred!';
    	            }
    	        }
    	        else {
    
    	            $status = 'Upload Fail: Unsupported file format or It is too large to upload!';
    	        }
    
    	        //echo out script that TinyMCE can handle and update the image in the editor
    
    	        return ("
    
    "); }
  • The second file is Resources\views\editor.blade.php
    • The only content we're worried about here is the implementation as it relates to the TinyMCE implementation. 
      • So first we'll start with the instantiation of the editor
      • Take special note of the line with image_list.  This specifies the URL that will produce the list of images available. 
       	tinymce.init({
      	    selector: "textarea",
      	    resize: "both",
      	    relative_urls: false,
      	    plugins: ["autoresize", "image", "code", "lists", "code","example", "link"],
      	    indentation : '20pt',
      	    file_browser_callback: function(field_name, url, type, win) {
      	        if (type == 'image') $('#my_form input').click();
      	    },
      	    image_list: "/imglist",
      	    toolbar: [
      	        "undo redo | styleselect | bold italic | link image | alignleft aligncenter alignright | preview | spellchecker"
      	    ]
      	});
      
      • The next part we need to take note of is eseentially a hidden form that is used by TinyMCE to produce the file input for the image upload.
 <iframe id="form_target" name="form_target" style="display:none"></iframe>
<form id="my_form" action="/upload" target="form_target" method="post" enctype="multipart/form-data" style="width:0px;height:0;overflow:hidden">

    <input type="hidden" name="_token" value="{{ csrf_token() }}">

    <input name="image" type="file" onchange="$('#my_form').submit();this.value='';">

</form>

Ok, with the code out of the way let me do some explaining.  First, I had no idea that the image upload required a hidden input for the upload to function, nor did I know it required a script to update the fields in the editor.  I came upon this by stumbling upon another site, with code for Python, http://pixabay.com/en/blog/posts/direct-image-uploads-in-tinymce-4-42/.  What I did was copy the Python code and replace it with the PHP code you see in the FileBrowserController.php. 

31 Comments
wrote on 01/27/2017 - 11:33am:

123123


wrote on 02/10/2017 - 04:53am:


marcovetrano wrote on 02/10/2017 - 04:53am:

tyutyu


wrote on 03/13/2017 - 01:55pm:


wrote on 03/13/2017 - 01:55pm:

Hola


Carlos mario wrote on 03/13/2017 - 01:56pm:

“OTTO” se mantiene como huracán categoría uno (1)  acuerdo la escala Saffir-Simpson, a


wrote on 03/13/2017 - 02:00pm:


wrote on 03/13/2017 - 02:00pm:


wrote on 03/24/2017 - 03:21pm:

One new comment First Second  Third


wrote on 03/25/2017 - 12:56am:

dfgdg


wrote on 03/31/2017 - 07:59pm:

wxcxwcxwc

wxcxwc


wrote on 04/05/2017 - 09:24am:

xvxcv


wrote on 04/05/2017 - 09:25am:

xvxcv


wrote on 04/24/2017 - 09:58pm:

mmm


wrote on 04/27/2017 - 03:09am:


wrote on 05/04/2017 - 01:57am:


wrote on 05/04/2017 - 05:40pm:

dasdas


asd wrote on 05/04/2017 - 05:40pm:

dasdas


wrote on 06/12/2017 - 11:45am:

sdfsdfsdfsdfsdfsdf


wrote on 06/13/2017 - 07:16am:

wdasdacs asddasddasdadasdasdadsasdasdasda


wrote on 06/13/2017 - 07:16am:

wdasdacs asddasddasdadasdasdadsasdasdasda


wrote on 06/13/2017 - 07:16am:

wdasdacs asddasddasdadasdasdadsasdasdasda


wrote on 06/13/2017 - 08:08am:

´º


wrote on 06/16/2017 - 05:03am:

hello there.


wrote on 06/16/2017 - 05:03am:

hello there.


wrote on 06/16/2017 - 05:03am:

hello there.


wrote on 07/12/2017 - 07:01am:


wrote on 07/25/2017 - 12:09pm:


asdf wrote on 07/30/2017 - 08:01am:

dsfsdfasdfasdf


wrote on 07/30/2017 - 08:01am:

dsfsdfasdfasdfdfasdfsdfsdfsdf


wrote on 07/30/2017 - 03:19pm:

Testgdzie hi hg ty hg DG KiB





Post Comment