Laravel Eloquent gotcha using With and Find

The Eloquent ORM in Laravel makes it easy to pull in related models using the ::with() method.  It’s very useful and can solve the N+1 Query problem that can occur when accessing related models in a loop from the parents records.

<?php
$data = MyParentModel->with('ChildModel');

You’d commonly want to use this when accessing a particular parent model using the ::find() or ::findOrFail() method. The trap can be that with() must be called before findOrFail().

If you chain methods and call findOrFail() first it will be ignored and your result set will include all parent rows!

<?php
$data = MyParentModel->with('ChildModel')->findOrFail($parent_id);

Laravel 5 Environment Config

Laravel 4 used a function that checked the servers hostname to determine the environment. Laravel 5 simplifies environment detection by having a .env file present in your project root.

.env.example is ignored by Laravel’s detection. You can fill it with the keys your application expects to act an an example for your own file.

.env is for the current environment

Add .env to your .gitignore file. It’s got to stay out of your repo so you don’t overwrite it each time you pull.
Copy/Rename .env.example to .env for each environment.

set the APP_ENV value within your .env file to tell Laravel where it’s running.

APP_ENV=local
APP_DEBUG=true
APP_KEY=123abc...
$app->environment(); //get the current environment
if($app->environment('local', 'staging')) { }  //test if local or staging env

You can retrieve your .env config values with the env() function.


$cfgValue = env('MY_SWEETAS_VARIABLE');

Detecting Environment in Laravel 4

Update: How to Get Environment in Laravel 5

Your PHP application should have different settings for its development and production environments. Here’s how you can set your Laravel 4 app to detect the environment, load the appropriate settings and keep installation-specific things like database credentials out of your Git repo.

Detecting The Environment

Laravel lets you provide arrays of hostnames it will check the server against to determine the environment.

Open bootstrap/start.php

$env = $app->detectEnvironment([
   'local' => ['MyMachineName', 'AnotherDevMachine'],
   'staging' => ['StagingEnvName']
]);

If unsure, use PHP’s gethostname() function to find your machine names.
This is the value to use inside the local/staging arrays

Laravel will default to ‘production’ if no other environment is matched.

 

Setting Environment Config Values

Laravel looks for .env.*.php files in the root directory (beside your composer.json and .gitignore files).

You will want to exclude these files from your Git repo. Add the following lines to your .gitignore

.env.*.php
.env.php

Then create an env file for each of your environments. Use .env.php for the production environment.
They should look something like this:

<?php

/**
 * Local Development
 */
 return array(
	'app.env'		=> 'dev',
	'app.debug'		=> true,
	'app.url'		=> 'http://example.dev',

	'mysql.host'	 => '127.0.0.1',
	'mysql.database' => 'bestDbEva',
	'mysql.username' => 'me',
	'mysql.password' => 'myTremendousPassword'

 );

The actual values are up to you. You can store whatever values you need within the application.

Using The Environment Values

Laravel config can now call getenv() to get the dynamic environment variable. For your DB config open app/config/database.php

'mysql' => array(
	'driver'    => 'mysql',
	'host'      => getenv('mysql.host'),
	'database'  => getenv('mysql.database'),
	'username'  => getenv('mysql.username'),
	'password'  => getenv('mysql.password'),
	'charset'   => 'utf8',
	'collation' => 'utf8_unicode_ci',
	'prefix'    => '',
),