In this article you’ll learn how to use Laravel’s Artisan command line tool, and how to create a customized command. Note that you need to be familiar with the Laravel framework to get the most of this article.
In this tutorial we’re going to build a command to minify our css assets, which will be used like this:
<span>cssmin 'output_path' 'file1'...'fileN' --comments --concat</span>
Artisan is the name of the command line utility in Laravel. It comes with a set of predefined commands, which you can list with php artisan list. If you want to show the help for a specific command, you can use php artisan help command.
To create an artisan command, you can use the command:make command. This command accepts one argument:
and three options:
Now, to create our command we will use php artisan command:make CssMinCommand --command=cssminwhich will create a CssMinCommand.php file within our app/commands directory.
<span>cssmin 'output_path' 'file1'...'fileN' --comments --concat</span>
Our CssMinCommand class extends the IlluminateConsoleCommand and overrides two methods ( getArguments, getOptions ).
Note: options may or may not have values, --comments is only a flag that returns true if it’s passed to the command, whereas --ouptput='public/assets' will return a value.
When your command is executed, the fire method is called, so this is where we need to put our command logic.
if you try to run our command php artisan cssmin 'args' you’ll get a Command "cssmin" is not defined.
To register a command you need to add it to the artisan.php file:
<span>use Illuminate<span>\Console\Command</span>; </span><span>use Symfony<span>\Component\Console\Input\InputOption</span>; </span><span>use Symfony<span>\Component\Console\Input\InputArgument</span>; </span> <span>class CssminCommand extends Command{ </span> <span>protected $name = 'cssmin'; </span> <span>protected $description = 'Command description.'; </span> <span>public function __construct(){ </span> <span><span>parent::</span>__construct(); </span> <span>} </span> <span>public function fire(){ </span> <span>// </span> <span>} </span> <span>protected function getArguments(){ </span> <span>return array( </span> <span>array('example', InputArgument<span>::</span>REQUIRED, 'An example argument.'), </span> <span>); </span> <span>} </span> <span>protected function getOptions(){ </span> <span>return array( </span> <span>array('example', null, InputOption<span>::</span>VALUE_OPTIONAL, 'An example option.', null), </span> <span>); </span> <span>} </span><span>}</span>
If you don’t want to put your commands in the artisan.php file, you can create a separate file and include it, or if you’re creating a package you can register them in your Service Provider.
In our getArguments method we will define our output and files.
To define an argument, we need to pass an array of values:
<span>Artisan<span>::</span>add( new CssMinCommand ); </span> <span>//or through the container </span><span>Artisan<span>::</span>add( App<span>::</span>make("CssMinCommand") );</span>
mode: can have one of the three options:
However, you can combine them like InputArgument::IS_ARRAY | InputArgument::REQUIRED (argument is required and must be an array).
So our getArguments method will be:
<span>array( 'name', 'mode', 'description', 'defaultValue' )</span>
Note: when using the IS_ARRAY argument it should be the last one on the returned arguments array. (obviously).
Our cssmin command will only have two options. To define an option we pass an array:
<span>protected function getArguments(){ </span> <span>return array( </span> <span>array( </span> <span>'output', </span> <span>InputArgument<span>::</span>REQUIRED, </span> <span>'Path to output directory' </span> <span>), </span> <span>array( </span> <span>'files', </span> <span>InputArgument<span>::</span>IS_ARRAY | InputArgument<span>::</span>OPTIONAL , </span> <span>"List of css files to minify" </span> <span>), </span> <span>); </span> <span>}</span>
mode: can be one of the four options (InputOption::VALUE_IS_ARRAY, InputOption::VALUE_OPTIONAL, InputOption::VALUE_REQUIRED, InputOption::VALUE_NONE), the first three values are similar to the arguments.
description: useful when printing the command help.
So our getOptions method will be:
<span>cssmin 'output_path' 'file1'...'fileN' --comments --concat</span>
When our fire method is called we need to gather our arguments and options. We can make a separate function to do that for us:
<span>use Illuminate<span>\Console\Command</span>; </span><span>use Symfony<span>\Component\Console\Input\InputOption</span>; </span><span>use Symfony<span>\Component\Console\Input\InputArgument</span>; </span> <span>class CssminCommand extends Command{ </span> <span>protected $name = 'cssmin'; </span> <span>protected $description = 'Command description.'; </span> <span>public function __construct(){ </span> <span><span>parent::</span>__construct(); </span> <span>} </span> <span>public function fire(){ </span> <span>// </span> <span>} </span> <span>protected function getArguments(){ </span> <span>return array( </span> <span>array('example', InputArgument<span>::</span>REQUIRED, 'An example argument.'), </span> <span>); </span> <span>} </span> <span>protected function getOptions(){ </span> <span>return array( </span> <span>array('example', null, InputOption<span>::</span>VALUE_OPTIONAL, 'An example option.', null), </span> <span>); </span> <span>} </span><span>}</span>
The argument and option methods take a key as an argument and return the appropriate value.
To keep our example clean and simple we will use this simple function with a small modification for the minification process.
<span>Artisan<span>::</span>add( new CssMinCommand ); </span> <span>//or through the container </span><span>Artisan<span>::</span>add( App<span>::</span>make("CssMinCommand") );</span>
Now to process our arguments (files) we’re going to make a separate method to do the job.
<span>array( 'name', 'mode', 'description', 'defaultValue' )</span>
Finally, our fire method will only call the two methods:
<span>protected function getArguments(){ </span> <span>return array( </span> <span>array( </span> <span>'output', </span> <span>InputArgument<span>::</span>REQUIRED, </span> <span>'Path to output directory' </span> <span>), </span> <span>array( </span> <span>'files', </span> <span>InputArgument<span>::</span>IS_ARRAY | InputArgument<span>::</span>OPTIONAL , </span> <span>"List of css files to minify" </span> <span>), </span> <span>); </span> <span>}</span>
Tip: You can also run an external command using the call method.
<span>array('name', 'shortcut', 'mode', 'description', 'defaultValue')</span>
To test our command, we’re going to copy some css files into our public/css directory, and then run the command.
<span>protected function getOptions(){ </span> <span>return array( </span> <span>array('comments', 'c', InputOption<span>::</span>VALUE_NONE, 'Don\'t strip comments' , null), </span> <span>array('concat', null, InputOption<span>::</span>VALUE_NONE, 'Concat the minified result to one file' , null), </span> <span>); </span> <span>}</span>
The first command will create two files (style.min.css, responsive.min.css) on the public/css directory.
Because we used the --comments and --concat flags, we’re going to get a file called all.min.css containing the two files with comments left.
Our command is not very descriptive and doesn’t give any messages or notifications!
Before we continue, on the final GitHub repository I will create a new tag for our command so you can switch and test each one.
To make the command a little verbose, Laravel provides us with some output functions:
<span>private function init(){ </span> <span>// retrun an array </span> <span>$this->files = $this->argument('files'); </span> <span>// return a string </span> <span>$this->output_path = $this->argument('output'); </span> <span>// return true if passed, otherwise false </span> <span>$this->comments = $this->option('comments'); </span> <span>// return true if passed, otherwise false </span> <span>$this->concat = $this->option('concat'); </span><span>}</span>
This will output:
Beside just displaying messages, you can ask the user for information, ex:
<span>private function minify( $css, $comments ){ </span> <span>// Normalize whitespace </span> <span>$css = preg_replace( '/\s+/', ' ', $css ); </span> <span>// Remove comment blocks, everything between /* and */, unless preserved with /*! ... */ </span> <span>if( !$comments ){ </span> <span>$css = preg_replace( '/\/\*[^\!](.*?)\*\//', '', $css ); </span> <span>}//if </span> <span>// Remove ; before } </span> <span>$css = preg_replace( '/;(?=\s*})/', '', $css ); </span> <span>// Remove space after , : ; { } */ > </span> <span>$css = preg_replace( '/(,|:|;|\{|}|\*\/|>) /', '', $css ); </span> <span>// Remove space before , ; { } ( ) > </span> <span>$css = preg_replace( '/ (,|;|\{|}|\(|\)|>)/', '', $css ); </span> <span>// Strips leading 0 on decimal values (converts 0.5px into .5px) </span> <span>$css = preg_replace( '/(:| )0\.([0-9]+)(%|em|ex|px|in|cm|mm|pt|pc)/i', '.', $css ); </span> <span>// Strips units if value is 0 (converts 0px to 0) </span> <span>$css = preg_replace( '/(:| )(\.?)0(%|em|ex|px|in|cm|mm|pt|pc)/i', '0', $css ); </span> <span>// Converts all zeros value into short-hand </span> <span>$css = preg_replace( '/0 0 0 0/', '0', $css ); </span> <span>// Shortern 6-character hex color codes to 3-character where possible </span> <span>$css = preg_replace( '/#([a-f0-9])\1([a-f0-9])\2([a-f0-9])\3/i', '#', $css ); </span> <span>return trim( $css ); </span> <span>}//minify</span>
The confirm method takes two arguments, a question message and a default value if the user type something different than y/n.
The ask method will ask the user for an input instead of just y/n, and if it’s left empty, the default value is returned.
The choice method will give the user a numbered list to choose from, and if it’s left empty, the default value is returned.
The secret method will prompt the user with a question and hide the typing, but the user input will be returned.
In fact, Laravel is just making Symfony’s Console API simpler and more verbose, and there is so much more if you want dig in.
Let’s make our command more verbose and keep the user updated about the performed tasks.
<span>private function processFiles(){ </span> <span>// array of minified css </span> <span>$css_result = []; </span> <span>foreach ( $this->files as $file ) { </span> <span>//read file content </span> <span>$file_content = file_get_contents( $file ); </span> <span>//minify CSS and add it to the result array </span> <span>$css_result[] = $this->minify( $file_content, $this->comments ); </span> <span>}//foreach </span> <span>// if the concat flag is true </span> <span>if( $this->concat ){ </span> <span>// join the array of minified css </span> <span>$css_concat = implode( PHP_EOL, $css_result ); </span> <span>// save to file </span> <span>file_put_contents($this->output_path . '/all.min.css', $css_concat); </span> <span>}//if </span> <span>else{ </span> <span>foreach ($css_result as $key => $css) { </span> <span>//remove '.css' to add '.min.css' </span> <span>$filename = basename( $this->files[$key], '.css' ) . '.min.css'; </span> <span>// save to file </span> <span>file_put_contents($this->output_path . '/' . $filename, $css); </span> <span>}//for </span> <span>}//else </span> <span>}//processFiles</span>
Our function now prints some useful messages to keep track of what’s going on.
Note: This will be tagged as v2 of our command on the GitHub repository.
When creating an application, we are used to dumping the list of available routes (php artisan routes).
Symfony provides a function that lets you print a such table easily. Check the documentation for an example. We’ll see next how we can use some Symfony Console Helpers.
To illustrate the use of some Symfony Helpers we will use the Progress Helper to keep the user updated about the job progress.
At the end of our init method we will require a progress from the HelperSet, then start our progress bar.
<span>cssmin 'output_path' 'file1'...'fileN' --comments --concat</span>
The start method accepts two arguments, $this->output is a ConsoleOuput instance from the Symfony Console. The second argument is the maximum number of steps.
Every time we process a file in our processFiles method we will advance the progress bar by one step, and when the job is done we will end the progress bar and print a notification message.
<span>use Illuminate<span>\Console\Command</span>; </span><span>use Symfony<span>\Component\Console\Input\InputOption</span>; </span><span>use Symfony<span>\Component\Console\Input\InputArgument</span>; </span> <span>class CssminCommand extends Command{ </span> <span>protected $name = 'cssmin'; </span> <span>protected $description = 'Command description.'; </span> <span>public function __construct(){ </span> <span><span>parent::</span>__construct(); </span> <span>} </span> <span>public function fire(){ </span> <span>// </span> <span>} </span> <span>protected function getArguments(){ </span> <span>return array( </span> <span>array('example', InputArgument<span>::</span>REQUIRED, 'An example argument.'), </span> <span>); </span> <span>} </span> <span>protected function getOptions(){ </span> <span>return array( </span> <span>array('example', null, InputOption<span>::</span>VALUE_OPTIONAL, 'An example option.', null), </span> <span>); </span> <span>} </span><span>}</span>
You can try the command with multiple files or uncomment the sleep function line to see a live effect.
Note: This version will be tagged as v3 on the final repository.
In this article we’ve learned how create and extend Laravel commands. Laravel has a lot of built-in commands that you can explore, and you can also check our final repository on GitHub to test the final result. Questions? Comments? Would you like to see more Artisan Command tutorials? Let us know!
Minifying CSS in Laravel is a crucial step in optimizing your website or application. It involves the process of removing unnecessary characters such as spaces, comments, and line breaks from the CSS files. This process reduces the size of the CSS files, which in turn reduces the amount of data that needs to be transferred to the client. This can significantly improve the load time of your website or application, providing a better user experience.
Laravel Mix is a powerful tool that provides a fluent API for defining Webpack build steps for your Laravel application. It supports several common CSS and JavaScript pre-processors, including minification. By using Laravel Mix, you can easily minify your CSS files with a single command, without having to manually remove unnecessary characters. This not only saves time but also ensures that your CSS files are as optimized as possible.
Yes, you can minify CSS files without using Laravel Mix. There are several online tools and npm packages available that can help you minify your CSS files. However, using Laravel Mix is recommended as it integrates seamlessly with Laravel and provides a simple and convenient way to manage and optimize your CSS files.
While minifying CSS in Laravel is generally a straightforward process, you might encounter issues if your CSS files contain syntax errors. These errors can cause the minification process to fail, resulting in unoptimized CSS files. Therefore, it’s important to ensure that your CSS files are error-free before attempting to minify them.
If you encounter issues during CSS minification in Laravel, you can use Laravel Mix’s source maps feature to debug them. Source maps are files that map the minified CSS files back to the original source files, allowing you to easily trace and fix any issues.
Yes, you can automate the process of CSS minification in Laravel by using Laravel Mix’s versioning feature. This feature automatically minifies your CSS files whenever you run the production build command. This ensures that your CSS files are always optimized, without having to manually minify them each time.
CSS minification can significantly improve the performance of your Laravel application. By reducing the size of your CSS files, you can reduce the amount of data that needs to be transferred to the client. This can result in faster load times, providing a better user experience.
Yes, besides CSS files, Laravel Mix can also be used to minify JavaScript files. This can further optimize your Laravel application, reducing the amount of data that needs to be transferred to the client.
Minifying CSS files involves removing unnecessary characters to reduce their size, while concatenating CSS files involves combining multiple CSS files into a single file. Both processes can help optimize your Laravel application, but they serve different purposes. Minifying reduces the size of each individual CSS file, while concatenating reduces the number of HTTP requests by combining multiple files into one.
To ensure that your minified CSS files are served correctly, you can use Laravel Mix’s versioning feature. This feature appends a unique hash to the filenames of your minified CSS files, ensuring that the client always receives the latest version of your CSS files.
The above is the detailed content of How to Create a Laravel CSS-Minify Command. For more information, please follow other related articles on the PHP Chinese website!