Call to undefined method Illuminate\Database\Schema\MySqlBuilder::defaultStringLength() - php

Firstly i was getting an error in
php artisan migrate
as
SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes
and Then i found a post on laracasts to fix this as
use Illuminate\Support\Facades\Schema;
public function boot()
{
Schema::defaultStringLength(191);
}
After adding this, when i run
php artisan optimize
then i am presented with new error as below
Call to undefined method Illuminate\Database\Schema\MySqlBuilder::defaultStringLength()
Please assist in getting rid of all these errors.

defaultStringLength is introduced in Laravel v5.4. Reference.
You can update the Laravel version
OR
You specify the length as $table->string('coumname', 255); You cannot specify more than 255. If you leave the length parameter it will assign 255 by default

This is because Laravel 5.4 uses the utf8mb4 character set by default, which includes support for storing “emojis” in the database. You can choose any one from these 2 solutions:
1) Change
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
to
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
2) Edit AppServiceProvider located at App\Providers\AppServiceProvider.php and add the following line to the boot() method and load the Schema facade:
use Illuminate\Support\Facades\Schema;
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
Schema::defaultStringLength(191);
}
What that will do is actually change the default maximum field length in the database and actually shorten your maximum string length from 255 to maximum of 191 characters (utf8 uses 3 bytes per character while utf8mb4 uses 4 bytes per character your field can now hold 25% less characters 255 * 75% = 191.25). So if you don’t set the string field by hand in the migration the new default will be 191.

Find AppServiceProvider in Laravel Project
1.First Add Facade
use Illuminate\Support\Facades\Schema;
2.Add Below lines in boot function
function boot() {
Schema::defaultStringLength(191);
}

Add use Illuminate\Support\Facades\Schema; to your AppServiceProvider.php file in App/Providers folder.
Add Schema::defaultStringLength(191); to the boot function.

If Laravel < 5.4
1. Find AppServiceProvider in Laravel Project
2. Comment line or remove Schema::defaultStringLength(191) in boot method

Related

Laravel 9 - Eloquent model : Trying to load self model parents recursively

I'm trying to migrate a Laravel 5 API with MySQL 5.7 to a Laravel 9 API with MySQL 8.
Almost everything is working well, except on a few queries that tries to load data with their parent, recursively.
On Laravel 5, i came up with this following solutions : Recursive Eloquent Models | Laravel ORM from self referencing table get N level hierarchy JSON
It was working like a charm, but on Laravel 9, I get a HTTP 500 error from Apache, which tells me in the logs the following error :
PHP Fatal error: Allowed memory size of 134217728 bytes exhausted
(tried to allocate 262144 bytes)
I tried at first to increase the memory in php.ini, but it was getting worst as the server was getting very laggy, so I had to restart Apache and go back with the 128M default value. Also on my Laravel 5 environment, I did not need to increase memory.
I was also suspecting the MySQL 8 upgrade to be involved in this problem, but by connecting to my MySQL 5.7 database, i had the same issue, so I think it comes from the way that Laravel loads relations in the 9 version.
Here is my Model code :
<?php
namespace App\Models\Consommation;
use Illuminate\Database\Eloquent\Model;
class ConsoRequestAttribut extends Model
{
protected $table = 'conso_request_attribut';
public $incrementing = false;
protected $primaryKey = 'id_attribut';
public $timestamps = false;
const ERROR_DELETE_ATTRIBUTE = 1;
const SUCCESS_DELETE_ATTRIBUTE = 0;
protected $fillable = [
'id_attribut',
'code_type_attribut',
'valeur',
'id_parent_attribut'
];
public function parent_attribut() {
return $this->belongsTo('App\Models\Consommation\ConsoRequestAttribut', 'id_parent_attribut', 'id_attribut');
}
public function parent() {
return $this->parent_attribut()->with('parent');
}
...
}
So on my Laravel 9 app, if I remove the ->with('parent') in my parent() function, the query result is returned and I don't have a 500 HTTP error, so I think the problem is with recursive loading.
Any idea ?
Thanks
It is better to call nested relationships like this:
public function parent() {
return $this->with('parent_attribut.parent');
}
I did not succeed to load the parent entity recursively with my ConsoRequestAttribut model, as I'm still stuck with the same memory problem. So it's not really "resolved".
As an alternative, in my ConsoRequestAttributRepository class, I made a function to load parent of entity recursively, which works perfectly :
public function retrieveRecursivelyConsoRequestAttributeParent(ConsoRequestAttribut $attribut)
{
$parent = ConsoRequestAttribut::where('id_attribut', $attribut->id_parent_attribut)
->first();
$attribut->parent = $parent;
if($parent->id_parent_attribut != null)
$this->retrieveRecursivelyConsoRequestAttributeParent($parent);
}

What and Where comes the actual usage of LARAVEL_START const defined in index.php of Laravel 5.7?

When I'm looking into the Laravel Request Cycle, I encountered this line of code in the file index.php
define('LARAVEL_START', microtime(true));
I didn't find any specification about this in Laravel documentation, may be it's not Laravel specific, who knows. Also I can't find any usage of this either in the documentation or any other place, please help me to understand what this line of code actually for?
define('LARAVEL_START', microtime(true));
This line essentialy starts up the timer, so you can time how long it takes to boot up the framework, etc. Fun fact is that this constant is never used throughout entire framework, but you already noticed it.
If you are using vendor\bin\phpunit to run your tests
public function __construct(?string $name = null, array $data = [], string $dataName = '')
{
parent::__construct($name, $data, $dataName);
define('LARAVEL_START', microtime(true));
}
Add this to your constructor of TestCase.php

Laravel filesystem sftp cached adapter

I am struggling with this issue for some time.
I am using the sftp adapter to connect to another server where i read/write files a lot.
For thumbnail creation i use background jobs with laravel horizon to retrieve pdf contents from the remote sftp server and then generate a jpg and place in local filesystem.
For first setup i need to make around 150k of thumbnails.
When i use a lot of processes in horizon the remote server can't handle this number of connections.
I must limit to max 2 processes at the moment (10 secs~ * 150k~) not optimal.
I want to cache the connection because i know it is possible and probably solves my problem, but can't get it to work:(
The only reference/tutorial/example/docs i could find is
https://medium.com/#poweredlocal/caching-s3-metadata-requests-in-laravel-bb2b651f18f3
https://flysystem.thephpleague.com/docs/advanced/caching/
When i use the code from the example like this:
Storage::extend('sftp-cached', function ($app, $config) {
$adapter = $app['filesystem']->createSftpAdapter($config);
$store = new Memory();
return new Filesystem(new CachedAdapter($adapter->getDriver()->getAdapter(), $store));
});
I get the error: Driver [] is not supported.
Is there anyone here who can help me a bit further on this?
It appears necessary to adjust your configuration:
In your config/filesystems.php file, add a 'caching' key to your storage:
'default' => [
'driver' => 'sftp-cached',
// ...
'cache' => [
'store' => 'apc',
'expire' => 600,
'prefix' => 'laravel',
],
],
This example is based on official documentation (https://laravel.com/docs/5.6/filesystem#caching), but it is not described well how the 'store' key is used here (where memcached is the example), and you would need to change the implementation of your driver to new Memcached($memcached); (with an instance to inject) instead.
In your case, since the sftp-cached driver implements $store = new Memory();, the cache config must reflect this with 'store' => 'apc' (which is RAM based cache). Available 'store' drivers are found in config/cache.php.
(If you use APC and get an error message Call to undefined function Illuminate\Cache\apc_fetch(), this PHP extension must be installed, see e.g. http://php.net/manual/en/apcu.installation.php)
Finally, I believe the 'prefix' key in config/filesystems.php must be set to the same as the cache key prefix in config/cache.php (which is 'prefix' => 'cache' by default).

Laravel ModelFactory error when seeding

My ModelFactory:
<?php
$factory->define(App\Models\Customer::class, function (Faker\Generator $faker) {
return [
'name' => $faker->company,
'email' => $faker->unique()->safeEmail,
'status'=> $faker->numberBetween($min = 0, $max = 2),
'slug'=> $faker->slug,
];
});
Database seeder
<?php
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
$customers= factory(App\Models\Customer::class, 100)->create();
}
}
When I run
php artisan db:seed
I get the error
[Symfony\Component\Debug\Exception\FatalThrowableError]
Parse error: syntax error, unexpected '->' (T_OBJECT_OPERATOR), expecting '
]'
I've tried everything I can think of, but can't find the problem...
Edit:
I forgot to mention that this was working fine a day earlier and then "broke" as I started to add more ModelFactories (in separate files). I then discarded all my changes (from source control) to be 100% sure I hadn't changed anything. The only other aspect could be that I have something in the .gitignore that may have updated and wasn't rolled back:
/node_modules
/public/storage
/public/hot
/storage/*.key
/.idea
Homestead.json
Homestead.yaml
It seems the problem is this line:
'status'=> $faker->numberBetween($min = 0, $max = 2),
It should be:
'status'=> $faker->numberBetween(0, 2),
Ok, so I found the reason and feel really idiotic about it, but posting it here anyway in case someone follows in my footsteps.
The issue was that there were other ModelFactories in the database/factories folder and it seems that running php artisan db:seed parses those files as well, even though they are not referenced in the DatabaseSeeder class. One of those files had incorrect one-many syntax and that was causing the error.
The only way I realized it was that I ran the factory->create method within php artisan tinker and the error message it threw up referenced this other factory definition.
FWIW, I then used the approach outlined here for my relationships - for the reasons mentioned in the question there...

Error in migrating Laravel after make:auth

I am trying to learn Laravel 5.4. After I publish the command php artisan make:auth and publish the command php artisan migrate the following errors get displayed and some database tables do not get greated:
[Illuminate\Database\QueryException]
SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key
was too long; max key length is 767 bytes (SQL: alter table users
add unique users_email_unique(email)) [PDOException]
SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key
was too long; max key length is 767 bytes
Regarding the fact that I need to use some columns as a container of characters having Persian Script Font (some other columns contain English, Spanish ... characters), I created the MySQL database with utf8_general_ci and I suppose that the errors are initiated because of the database's encoding. Would you please tell me what character encoding I shall use to build the database with to be able to leverage Laravel's Auth capabilities? Thank you very much in advance.
Let's see SHOW CREATE TABLE so we can see the definition of email.
Meanwhile, I will guess that it includes something like
email VARCHAR(255) CHARACTER SET utf8mb4,
INDEX(email)
Do one of these (each has its drawbacks):
255 -> 191 (but make sure you don't currently have longer addresses)
utf8mb4 -> utf8 (thereby disallowing Emoji and some Chinese characters)
INDEX(email(20)) (If it is UNIQUE or PRIMARY KEY, do not pick this option)
It is possible to reconfigure (if after 5.6.3) the server and table to allow bigger indexes; this is not the 'default' until 5.7.7.
Laravel 5.4 has a documented issue on this error.
For others who run into this problem this is also a good fix:
open your app\Provider\AppServiceProvider.php
change it to:
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
Schema::defaultStringLength(191); //
}
/**
* Register any application services.
*
* #return void
*/
public function register()
{
//
}
}
run migration again

Categories