What is `protected $fillable` in a Laravel model?

In Laravel, the `protected $fillable` property is used to define an array of attributes that are mass assignable. This means these attributes can be assigned using mass-assignment techniques, such as when creating a new model instance or updating an existing one using the `create` or `update` methods.

Mass Assignment

Mass assignment is a way to assign multiple attributes to a model instance in a single step, typically using an array. For example, you might have a form where a user can submit several pieces of information at once. Instead of assigning each piece of information individually, you can pass the entire array to the `create` or `update` method.

Here’s an example of how you might use the `$fillable` property in a Laravel model:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    // Define the attributes that are mass assignable
    protected $fillable = [
        'title', 
        'content', 
        'author_id'
    ];
}

In this example, the `Post` model has three attributes (`title`, `content`, and `author_id`) that are mass assignable.

Using Mass Assignment

With the `$fillable` property defined, you can now safely use mass assignment:

// Creating a new post
$post = Post::create([
    'title' => 'My First Post',
    'content' => 'This is the content of my first post.',
    'author_id' => 1
]);

// Updating an existing post
$post->update([
    'title' => 'Updated Title',
    'content' => 'This is the updated content.'
]);

The primary purpose of the `$fillable` property is to prevent mass-assignment vulnerabilities. Without `$fillable` (or its counterpart `$guarded`), any attribute in the model can be mass assigned, which could potentially allow malicious users to update sensitive fields that they shouldn’t have access to.

Mass Assignment Vulnerability

So what is this mass assignment vulnerability? Consider a scenario where a user can submit their profile information. If the user model has an attribute like `is_admin`, and this attribute is not protected, a malicious user could submit a form with an `is_admin` field and set its value to `true`, giving themselves admin privileges.

By defining the `$fillable` property, you explicitly specify which attributes are safe to be mass assigned, thus mitigating this risk.

So, using the `$fillable` property is a best practice in Laravel to ensure that only the intended attributes can be mass assigned, enhancing the security of your application.

Download latest Laragon & Install Laravel 9

I like to use Laragon sometimes for my Laravel development. I had Laragon 5 installed and wanted to create new Laravel 9 project. When I selected Quick App-> Laravel it installed Laravel 8! I looked at Laragon website but the latest one there is Laragon 5 with PHP 7. Laravel 9 requires PHP 8.

Good news is that Laragon has already updated to Laragon 6 with PHP 8 but for some reason there is no downlaod link on their downlaod page (at the time of writing this post).

So what you need to do is go to Laragon github page and download latest laragon-wamp.exe from there. Then you do a backup of your current laragon folder on your PC and then just install the latest Laragon – it will keep all your files and settings, just upgrade to latest Laragon with PHP 8.

After you are done right click the Laragon icon, quick app and Laravel and it will install Laravel 9 (and probably next versions as long as they require PHP 8)

Laravel – Remove Public from URL

Why is my Laravel URL mysite.com/public by default and how do I remove “public” from URL?

Probably the first question most people ask when they install their new Laravel site.

Here are 2 ways, luckily it is easy to do.

1. The most standard one is to just edit .htaccess file and add these lines:

<IfModule mod_rewrite.c>
   RewriteEngine On 
   RewriteRule ^(.*)$ public/$1 [L]
</IfModule>

Note: For this to work you must have mod_rewrite enabled on your Apache server because rewrite module is required to apply these settings.

2. This option is either easier or more complicated, depending on if you can edit ‘Document root’ on your hosting server. So, if you have access to Cpanel of your hosting AND they allow you to change ‘Document root’ then change it from let say “/public_html” to “/public_html/public”. That should do the trick.

If you can’t edit ‘Document root’ by yourself (security measure etc) then the best is to ask your host support to change it to “/public_html/public” (assuming your root folder for website is /public_html . If it is /www then let them change it to /www/public).

Curl Error : SSL certificate problem: unable to get local issuer certificate Laravel Wamp

Got this error when trying to use a Laravel API package that used Curl:

Curl Error : SSL certificate problem: unable to get local issuer certificate

I am using WAMP (local development) so the solution that worked was this (Let’s assume your PHP version is 7.1.9):

1. Download/save this file: http://curl.haxx.se/ca/cacert.pem into (your wamp path might differ) the C:\wamp64\bin\php\php7.1.9 folder.

2. Now you have to edit php.ini file but in my case it was not the one that is in the above folder (I tried that one first but still got the same error) but it was the one in this (your wamp and apache folder might differ) folder:  C:\wamp64\bin\apache\apache2.4.27\bin . The easiest way to open this file is to click on the green W (Wamp) icon in the tray, then PHP and then php.ini and Windows should open this file for you.

3. Find this line
;curl.cainfo
and change it to :
curl.cainfo = "C:\wamp614\bin\php\php7.1.9\cacert.pem"
Dont forget to remove the ; at the start of the line and of course use your wamp path.

4. Restart (or exit and start) the WAMP server and the error should be gone!

 

How to check Laravel version?

Every now and then you would like to check what version of Laravel do you have installed. How to determine that? Here are a couple of ways. I tested this for Laravel 4.

1. The easiest way is to simply run artisan command php artisan --version from your CLI and it will return your Laravel version:

check laravel version

2. You can also browse to and open file vendor\laravel\framework\src\Illuminate\Foundation\Application.php. You will see the version of your Laravel instalation near the top of the class, defined as a constant:

/**
	 * The Laravel framework version.
	 *
	 * @var string
	 */
	const VERSION = '4.0.10';

3. You can also place a little code in your routes.php file at the end and then access it like yourdomain.com/laravel-version . This of course assumes that there is nothing in your routes.php file that would not allow the access of /laravel-version route.

Route::get('laravel-version', function()
{
$laravel = app();
return "Your Laravel version is ".$laravel::VERSION;
});

Please keep in mind that it is best not to keep this code on your production server. It’s not that it is harmful but there is simply no need for this because the first two methods that I showed you are simpler. If you still want to keep it then maybe you can comment it out.

There are other ways, especially with code but why complicate things when these 3 are the easiest? 🙂

If you know some simpler ways then please let me know in the comments.

Laravel 4 with Twitter Bootstrap

One of the first thing many, including me, want to do after installing Laravel 4 is to add Twitter Bootstrap. If you go searching for this on Google you will get all kids of results that may confuse beginner. “Use Bower”, “Install it as a external package then use Basset” and several more. I think some are a little too complicated for a beginner and it doesn’t need to be. I know adding a line to composer.json is easy but this will usually (depending on whcih package you chose) download gazillion of files to your vendor folder.

Here is what to do for a simple website – you don’t need to treat it as a external package that needs to be added via composer, bower or be used with help of Basset etc. Sure, it’s easier to update it via composer but it is not that difficult to update it manually too – if you indeed need an update.

So here are few easy ways:

Use Bootstrap CDN links

Simply include 3 links, which will fetch your twitter bootstrap files from MaxCDN site. This is the easiest and fastest way. Let’s assume that you have a master blade template called default.blade.php. Place this code inside your HTML head section (anywhere):

<head>

<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css">

<!-- Optional theme -->
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap-theme.min.css">

<!-- Latest compiled and minified JavaScript -->
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.3/js/bootstrap.min.js"></script>

</head>

That’s it, you should now be able to use Twitter Bootstrap goodness.

Download Bootstrap and put it in your public folder

I like to host my own files and not depend on third party so I usually do this. Here we don’t treat Twitter Bootstrap as a Laravel package.We will bypass Composer so we manually put Twitter Bootstrap files into our public assets folder.

Go to getbootstrap.com, download Twitter Bootstrap ZIP file and extract the content of ZIP file (pull entire dist folder) to your /public/ folder. I usually rename dist folder to tb.

You will then end up with css,fonts and js folders inside /public/tb/ folder.

Now we follow the same procedure like before except that we will link to local files we just downloaded. I will use Laravel’s HTML helper to create links. {{ and }} is a Laravel Blade syntax.

<head>

{{ HTML::style('tb/css/bootstrap.css') }}
{{ HTML::style('tb/css/bootstrap-theme.min.css') }}
{{ HTML::script('tb/js/bootstrap.min.js') }}

</head>

As you can guess the first two lines will create CSS style links and the third one will create script link. If you view the source of generated page you will see that Laravel’s HTML helper created something like this (of course http://yoursite.dev will be replaced by your site) :

<head>

<link media="all" type="text/css" rel="stylesheet" href="http://yoursite.dev/tb/css/bootstrap.css">
<link media="all" type="text/css" rel="stylesheet" href="http://yoursite.dev/tb/css/bootstrap-theme.min.css">
<script src="http://yoursite.dev/tb/js/bootstrap.min.js"></script>

</head>

There are other ways (Bower, Composer, Basset…), which I might show in another post (or maybe I’ll update this post later) but these two are the easiest, especially for those just starting with Laravel 4.

Enjoy your Twitter Bootstrap powered Laravel 4 website 🙂

Laravel 4 profiler – Log and display SQL queries

Laravel 3 had a cool profiler bundle called Anbu, written by Daylee Rees. It was written as a bundle but Taylor, creator of Laravel, liked it so it was eventually included in the Laravel core. Laravel 4, at the time of this writing, however has no such profiler included in the core. So how do we display database SQL queries for debugging?

Here are a couple of solutions:

1. Use Loic Sharma’s Profiler. It is a PHP 5.3 profiler based off of Laravel 3’s Anbu. I have not tried this yet so just follow the instructions there.

2. Try Profiler by Juy, a PHP 5.3 profiler for Laravel 4. Backend based on sorora/omni, fronted based on loic-sharma/profiler, some features inspirated from papajoker/profiler, some features written by Juy.

3. Create an event that will listen to illuminate.query. Open your routes.php file and add this at the bottom:

 Event::listen('illuminate.query', function($sql)
 {
     var_dump($sql);
 }); 

This will print every query on the screen on the place where it is called so it might not look pretty,especially in loops. Also you might not see the queries on the screen in some cases since they will be “hidden” in the HTML source code (so just view the page source to see them, they will usually be at the top of the page)

4. You can also display the last executed query by placing a code in front of the code that executes a query. For example let say we have this code in our controller:

// Grab all the users
$customers = Customer::orderBy('name','asc')->get();

Place the Event::listen code in front of that statement and you will see that query displayed on your screen.

// dump the next executed query and die (dd)
Event::listen('illuminate.query', function($sql)
{
    dd($sql);
}); 

// Grab all the users
$customers = Customer::orderBy('name','asc')->get();

Keep in mind that this will only display 1 query. If your statement calls more queries they will not get displayed.

5. Put the following code in the App::before filter to get a dump of your database queries:

DB::listen(function($sql, $bindings, $time)
{
    var_dump($sql);
    var_dump($bindings);
});

6. There is another “trick” that I use sometimes (because having SQL queries displayed all the time is not practical and it messes up the code and design): I intentionally make an error in my SQL statement. For example here I mistyped type as tyspe:

$contracts = Contract::where('tyspe','=',0)->orderBy('note','asc')->get();

Since tyspe doesn’t exist Laravel returns an error,showing me the complete SQL statement:

SQLSTATE[42S22]: Column not found: 1054 Unknown column ‘tyspe’ in ‘where clause’ (SQL: select * from `contracts` where `tyspe` = ? order by `note` asc) (Bindings: array ( 0 => 0, ))

Let me know if you know of any other solutions in the comments.

Script php artisan clear-compiled handling the pre-update-cmd event returned with an error

I had a problem with Basset package (website didn’t load, it kept timing out) so I tried to remove it from the composer.json file to see if it helps. After running php composer.phar update I got this error:

Script php artisan clear-compiled handling the pre-update-cmd event returned with an error

You can even get this error:

Script php artisan optimize handling the post-update-cmd event returned with an error

To fix this error open your composer.json file and delete the scripts key (or just the part that fails – in bold). In my case it was this:

	"scripts": {
		"pre-update-cmd": [
			"php artisan clear-compiled"
		],
		"post-install-cmd": [
			"php artisan optimize"
		],
		"post-update-cmd": [
			"php artisan optimize"
		]
	},

I ran php composer.phar update again and it worked.

Some people report that after this they have problems with running php artisan optimize and few others . I didn’t have this problem but if you have it then delete the app/bootstrap/compiled.php file and then try running php composer.phar update

Populate dropdown list from database with Laravel

While building admin/CMS or just a form on your site you might need to build a dropdown (select) list with values read from database. It is very elegant to do this with Laravel’s Eloquent. (For the sake of this post let’s assume that you want to read values from the database and not from some array stored in a class or somewhere else.)

Let’s suppose the database table is called “countries” and is already populated (You can get one here). It contains, you guessed it, a list of country names, which you would like to display in a HTML dropbox list.

First, create a model named “Country.php” (you can use artisan, excellent  Laravel 4 generators or create it manually. Keep in mind that the model name is singular (Country) and the database table is plural (Countries).

In your controller add:

$country_options = Country::lists('short_name', 'id');

Simple isn’t it? This will return an array of values like “[1] => Afghanistan [2] => Aland Islands”… (We are assuming that database field name containing country names is “short_name”).

Note: Personally I like Eloquent but in case you do not want to use Eloquent or/and do not want to have an empty Country.php model lying there just so you can populate drop-down then you can use Laravel’s Fluent Database Query Builder:

$country_options = DB::table('countries')->orderBy('short_name', 'asc')->lists('short_name','id'); 

Ok, now let’s send this to view with ->with :

return View::make('admin/customers/create')->with('country_options',$country_options);

In above case I am sending $country_options to admin view that is used to create customers.

In the view you display it like this:

 {{ Form::select('country', $country_options , Input::old('country')) }}

That is all it takes to have a functioning drop-down select box. As you can see we are using Laravel Blade template engine and Form class. With Input::old('country')) we re-populate it with old values (for example after the form is submitted and there are some errors)

How to combine more fields with concat

In another case (for “customers”) I needed to combine two table fields into one and then populate the drop down with it: customers “first_name” + “last_name” should be “first_name last_name”. You can do this by combining Fluent Query Builder with Eloquent:

$customer_options = Customer::select(DB::raw('concat (first_name," ",last_name) as full_name,id'))->lists('full_name', 'id');

As you can see we are mixing Eloquent and DB:raw method.

Note: If you only want to use Laravel’s Database Query Builder then you can do this:

$customer_options = DB::table('customers')->select(DB::raw('concat (first_name," ",last_name) as full_name,id'))->lists('full_name', 'id');

How to add default option to dropdown list

Sometimes we want to have some default value that gives us some instructions what to do (“Please select a country,…”) with the dropdown or maybe even some default “non-value” (in case user doesn’t want to select anything). The easiest way to do this is to add array('' => 'Select One') + so our code looks like this (few examples with the code in this post):

$country_options = array('' => 'Please Select Your Country') + Country::lists('short_name', 'id');
//or
$customer_options = array('' => 'Select Customer') + Customer::select(DB::raw('concat (first_name," ",last_name) as full_name,id'))->lists('full_name', 'id');
//and so on..

Keep in mind that you will have to add some validation (jQuery, Laravel’s own validation etc) in case user leaves the default option (in example above we leave the value as empty but you can set it to anything you want).

I really love Laravel 4, it makes developing so much fun and simple.

Laravel erorr: Call to undefined method Illuminate\Foundation\Application::getConfigLoader()

After I resolved my speed problems with Composer (see the post here ) I got this error once the Composer ended updating dependencies:

Fatal error: Call to undefined method Illuminate\Foundation\Application::getConfigLoader() in E:\path-to-my-project\vendor\laravel\framework\src\Illuminate\Foundation\start.php on line 106

As I already mentioned in my previous post I don’t know if this was due to me canceling composer updates several times or something else but the same error appeared when I opened my project URL in web browser.

The solution is simple: Delete bootstrap/compiled.php file.

After that run php artisan optimize command, which will generate new compiled.php file. I am not sure if this last step is necessary because everything seems to work even without the compiled.php file but I would advice to run this command just in case and regenerate compiled.php file.