I extended SonataUser with SonataEasyExtends so I have now a Application/Sonata/UserBundle
I have added a field in the model Application/Sonata/UserBundle/Resources/config/doctrine/User.orm.xml
Tried to update the setters & getters with
$ php app/console doctrine:generate:entities Application/Sonata/UserBundle/Entity/User
Seems to go well. Now trying to update the database
$ php app/console doctrine:schema:update --force
I get
PHP Fatal error: Access level to Application\Sonata\UserBundle\Entity\User::$groups must be protected (as in class FOS\UserBundle\Entity\User) or weaker in /home/glide/bouygues/src/Application/Sonata/UserBundle/Entity/User.php on line 26
So the question is: how should I properly update getters & setters in Entity/User.php, should I have to reuse EasyExtends ?
I came across this problem and the simple solution was to change the declaration of the groups variable from public to protected:
/**
* #var \Doctrine\Common\Collections\Collection
*/
protected $groups;
can you paste your entity and the xml config?
the error tends to mean your variable "$groups" needs to be protected so its either being declared as a "normal" var or private.
Related
Client.php
/**
* #ORM\ManyToOne(targetEntity="EnseigneNationale", inversedBy="clients")
* ...
*/
private ?EnseigneNationale $enseigneNationale;
/**
* #ORM\OneToMany(targetEntity="ClientBanque", mappedBy="client", cascade={"persist", "remove"})
* ...
*/
private ?Collection $clientBanques;
My data comes from an old database, I have to create a command that corrects some data in the database.
if (Condition) {
/** #var ClientBanque $clientBanque */
$clientBanque = $clientBanques[0];
$clientBanque->setAA($aa);
$this->manager->persist($client);
}
When I persist, I got the error saying that doctrine unable to find "EnseigneNationale", that it can be nullable and I m not using it in my persist changes.
Somthing wrong with my code ?? Help Please
PHP : 7.4
Symfony : 5.3
Doctrine : 2.4
It was me !! Sorry for disturb, I was adding $manger->clear() who breaks everything
What is happening is basically you've detached your object from entity manager. The object was removed from the identity map and is no longer managed by this entity manager.
You can attach the object back by calling $managedCopy = $em->merge($object);
Pay attention to the fact that merge returns a new object.
The state of the passed entity will be merged into a managed copy of this entity and this copy will subsequently be returned.
I am working on a new project in Symfony 5.3. I am using this command bin/console make:entity for creating entities.
This wizard automatically creates an entity with $id as primary key of type integer. I am prefering UUID instead of integer.
How I should change settings to get Entity like this?
Thank you
namespace App\Entity;
use App\Repository\EventRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\IdGenerator\UuidGenerator;
/**
* #ORM\Entity(repositoryClass=EventRepository::class)
*/
class Event
{
/**
* #ORM\Id
* #ORM\Column(type="uuid", unique=true)
* #ORM\GeneratedValue(strategy="CUSTOM")
* #ORM\CustomIdGenerator(class=UuidGenerator::class)
*/
private $id;
...
}
There is no option to set the generated identifier strategy on make entity.
You can see all available option using php bin/console make:entity -h
Also there are no configuration in doctrine.yaml file to define this.
It could be a good feature to add for current and next version
To request a new feature, you can create a new issue feature request type:
https://github.com/symfony/symfony/issues/new/choose
You will need a github account
I'm facing strange case. I face an error in production env not while in dev it's working fine.
Development:
Laravel 5.4.28
PHP 7.0.13
MYSQL 5.7.17
Production:
Laravel 5.4.28
PHP 7.2.1
MYSQL 5.7.20
In implementation code. I used:
namespace App;
use Illuminate\Support\Facades\Storage;
use Laravel\Scout\Searchable;
use Illuminate\Database\Eloquent\Model;
class Artwork extends Model
{
use Searchable;
In development it works fine. But in production it gives me this error:
count(): Parameter must be an array or an object that implements Countable
in Builder.php (line 936)
as you can see in this pic:
Any idea what is the reason behind this? and how to fix?
Put this code at the beginning of your route file, it will work fine
if(version_compare(PHP_VERSION, '7.2.0', '>=')) {
error_reporting(E_ALL ^ E_NOTICE ^ E_WARNING);
}
This is a documented change in PHP 7.2. You need to either update Laravel to 5.6 or downgrade PHP to version 7.1.
Replace
$originalWhereCount = count($query->wheres);
by
$originalWhereCount = count((array)$query->wheres);
in
\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Builder.php
I was facing similar issue in Laravel 5.6. Where I was getting error for object based array. I knew that data in that particular variable will always remain object so i used to convert the object to array. Here is code sample:
$objectData = (array)$objectData;
echo "Total Elements in array are: ".count($objectData);
My server was on PHP 7.1 when I updated to PHP 7.2 I got the same issue.
After searching I found why this occurs. (This occurs because of a PHP update.).
so in my case, the error is solved by typecasting.
I just update all code where I used to count
Before
//this is before
count($adminDetails)
After updated
//after update all i typecast all the code where i used count
count((array)$adminDetails)
Goodluck
This error occurs because you are using a higher PHP version and your Laravel application is on an older PHP version.
✅ Simple solution:
Open: app/Providers/AppServiceProvider.php
And in: public function register() { ... } function add following code:
if(version_compare(PHP_VERSION, '7.2.0', '>=')) {
error_reporting(E_ALL ^ E_NOTICE ^ E_WARNING);
}
In php 7.2+ count does not work on relation objects, you need to use:
$model->relation()->exists()
Not this (less than php 7.2):
count($model->relation)
i ran into the same problem (PHP 7.2 + Laravel 5.3) but i don't see any "good" answers here. For me, the problem occurs when i tried to start a Builder from a scope method on the model: SomeModel::forUser() calls scopeForUser(). Trying to build a new Query, it trips on a count($this->wheres) that gets no initial value (null). Because the magic static call to the scope starts the builder, no other conditions have been placed in the object so the property is still null at that point.
i thought it's worth sharing my solution first, then perspective on why i consider it better than Ben's answer. It's not personal, i just disagree.
Solution
i took a cue from this answer about overriding some of the core Illuminate\Database classes...
Extend Illuminate\Database\Eloquent\Model
Mine is App\Overrides\Database\Eloquent\Model
Extend Illuminate\Database\Eloquent\Builder
Mine is App\Overrides\Database\Eloquent\Builder
Extend Illuminate\Database\Query\Builder
Can you guess? App\Overrides\Database\Query\Builder
Tell Laravel to use YOUR Eloquent\Model:
config/app.php 'aliases' array, replace the 'Eloquent' value
with your Eloquent\Model FQN
My Model:
namespace App\Overrides\Database\Eloquent;
/*
* Notes:
* * Using replacement Query\Builder with ALIAS
* * Use of Builder in this class is MY Eloquent\Builder
*/
use App\Overrides\Database\Query\Builder as QueryBuilder;
use Illuminate\Database\Eloquent\Model as EloquentModel;
class Model extends EloquentModel
{
public function newEloquentBuilder($query)
{
return new Builder($query);
}
protected function newBaseQueryBuilder()
{
$conn = $this->getConnection();
$grammar = $conn->getQueryGrammar();
return new QueryBuilder($conn, $grammar, $conn->getPostProcessor());
}
}
My Eloquent\Builder:
namespace App\Overrides\Database\Eloquent;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
class Builder extends EloquentBuilder
{
public function __construct($query)
{
parent::__construct($query);
/*
* FIX #1: Set properties treated AS arrays
* to empty arrays on construct.
*/
$this->wheres = [];
// Any other properties treated as arrays should also be initialized.
}
}
My Query\Builder:
namespace App\Overrides\Database\Query;
use Illuminate\Database\Query\Builder as QueryBuilder;
class Builder extends QueryBuilder
{
public function __construct()
{
parent::__construct(...func_get_args());
/*
* FIX #2: Set properties treated AS arrays
* to empty arrays on construct.
*/
$this->wheres = [];
// Any other properties treated as arrays should also be initialized.
}
}
This safely preserves the framework's functionality, since the only actual change you're making is initializing properties that should have been in the first place. Everything else will pass instanceof checks used for dynamic loading and dependency injection.
Opinion
While i agree with #ben-harold about every comment he made saying "NEVER edit vendor code," i disagree with the "solution." It's an oversimplification to a much more complex problem.
Upgrade Laravel: to ensure support for PHP 7.2, jumping up several minor versions - if not major releases - is impractical for a lot of teams. As a long term objective, yes of course. As something i can do to get rid of the bug for my deadline? Nope. Upgrading takes a lot of planning and frequently a lot of rewrites as structures, names, and functionality change. It's something to prioritize, but not a need-it-now answer.
Downgrade PHP: same problem. Downgrading into PHP 5.x means A) PHP is EOL, which may be a deal breaker for a lot of customers who have security policies, and B) any usage of PHP 7.x language features have to be scrapped. As with upgrading the framework this is very likely to cause a lot of headaches. It's also an even less useful solution, since walking backward in the language just puts you farther behind and will require more long-term effort.
place the below line ob code before the class name in your controllers
if (version_compare(PHP_VERSION, '7.2.0', '>=')) {
// Ignores notices and reports all other kinds... and warnings
error_reporting(E_ALL ^ E_NOTICE ^ E_WARNING);
// error_reporting(E_ALL ^ E_WARNING); // Maybe this is enough
}
I was facing the same issue with an external created table (Not using migration or command),
After creating the model, I just assigned a table name, but the problem was in my model protected $fillable where I assign string instead of array and error occurred.
There is 2 possible solution for that.
Assign an array to your protected $fillable = ['filed1', 'filed2'];
Remove protected $fillable completely (Not Recommended)
class Abc extends Model
{
protected $table = 'cities';
protected $fillable = ['field1','field2', ...];
}
Model looking for countable parameter:
class ClassName extend Model {
protected $fillable=['column_name']; // column in DB of Model is in array
}
Before
count($collection['colors'])
Error:Expected type 'Countable|array'. Found 'string'
After
count((array)$collection['colors'])
It works for me!
'vendor\laravel\framework\src\Illuminate\Database\Eloquent\Builder.php' to:
$originalWhereCount = is_array($query->wheres) ? count($query->wheres) : 0;
I;m using laravel 6.x
for this case you can use this way:
$id = \DB::table('xxxx')->where('id', $id)->count();
I Solve this in Laravel 5.6
// in controller
public function index()
{
$todos = Todo::all();
return view('todos.index')->with(['todos' => $todos]);
}
// in view page
#if(count($todos) > 0)
#foreach($todos as $todo)
<div class="well">
<h3>{{$todo->text}}</h3>
<span class="label label-danger">{{$todo->due}}</span>
</div>
#endforeach
#endif
I have some namespaced migrations, and I can't get past the Class Not Found errors due to namespacing. In an earlier question, Antonio Carlos Ribeiro stated:
Laravel migrator doesn't play nice with namespaced migrations. Your best bet in this case is to subclass and substitute the Migrator class, like Christopher Pitt explains in his blog post: https://medium.com/laravel-4/6e75f99cdb0.
I have tried doing so (followed by composer dump-autoload, of course), but am continuing to receive Class Not Found errors. I've got the project files set up as
inetpub
|--appTruancy
|--database
|--2015_04_24_153942_truancy_create_districts.php
|--MigrationsServiceProvider.php
|--Migrator.php
The migration file itself is as follows:
<?php
namespace Truancy;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class TruancyCreateDistricts extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('districts', function($table) {
$table->string('id')->unique()->primary()->nullable(false);
$table->string('district');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('districts');
}
}
Migrator.php is as follows:
namespace Truancy;
use Illuminate\Database\Migrations\Migrator as Base;
class Migrator extends Base{
/**
* Resolve a migration instance from a file.
*
* #param string $file
* #return object
*/
public function resolve($file)
{
$file = implode("_", array_slice(explode("_", $file), 4));
$class = "Truancy\\" . studly_case($file);
return new $class;
}
}
MigrationServiceProvider.php is as follows:
<?php
namespace Truancy;
use Illuminate\Support\ServiceProvider;
class TruancyServiceProvider extends ServiceProvider{
public function register()
{
$this->app->bindShared(
"migrator",
function () {
return new Migrator(
$this->app->make("migration.repository"),
$this->app->make("db"),
$this->app->make("files")
);
}
);
}
}
The lines generated in autoload_classmap.php are as expected:
'Truancy\\Migrator' => $baseDir . '/appTruancy/database/migrations/Migrator.php',
'Truancy\\TruancyCreateDistricts' => $baseDir . '/appTruancy/database/migrations/2015_04_24_153942_truancy_create_districts.php',
'Truancy\\TruancyServiceProvider' => $baseDir . '/appTruancy/database/migrations/MigrationsServiceProvider.php'
I'm calling php artisan migrate --path="appTruancy/database/migrations" and I receive the error:
PHP Fatal error: Class 'TruancyCreateDistricts' not found in
C:\inetpub\laravel\vendor\laravel\framework\src\Illuminate\Database
\Migrations\Migrator.php on line 297
I know I must be doing something dumb (my instinct is $class = "Truancy\\" . studly_case($file); in Migrator.php is wrong), but I can't unscrew this lightbulb. The migrate command is obviously successfully finding my migrations file, and the correct classname is in the classmap, so it has to be somewhere in the process of resolving the classname itself from the file, which the subclass and substitution is supposed to address. Any suggestions as to where I've gone wrong?
Ok, I've gotten this working. It turns out that the Medium.com article assumes you'd just know where to put the files he talks about, which I didn't. I've made several changes, and now everything is working correctly:
I created a new appTruancy\providers subfolder, and add it to composer.json
I moved both Migrator.php and MigrationServiceProvider.php into the new folder
I changed the namespace in both of those files to Truancy\Providers to match the directory structure
I added 'Truancy\Providers\MigrationsServiceProvider' to the providers array in appTruancy\config\app.php
I added a \ in front of Schema in the migration file to reference the base namespace.
I ran dump-autoload to update the classmap
This is one of those cases where I'm not 100% certain that all of the changes were required, but the layout does make sense so I'm happy with it. So, in a nutshell, if you're trying to namespace your migrations, you need to subclass the Migrator class as described in the Medium.com article listed above, but you then need to register the service provider in config\app, making sure the class names in both files are consistent.
I'm trying to generate both entities and the database schema with Doctrine under CodeIgniter 2.0, using annotations. I'm not sure if I'm doing this correctly.
I've setup base classes which have only the classname and properties defined, and then annotated. I'm trying to use the generate-entities command to have it create the get/set methods.
<?php
namespace Entities;
include('ContentItem.php');
/**
* #Entity
* #Table(name="blobs")
*/
class Blob extends ContentItem {
/**
* #var ContentItemId
*
* #ManyToOne(targetEntity="ContentItem")
* #JoinColumn(name="contentitem_id", referencedColumnName="id")
*/
protected $contentitem;
/**
* #Column(type="string", length=64, nullable=true)
*/
protected $content;
/**
* #Column(name="date_created", type="datetime", nullable=false)
*/
protected $date_created;
/**
* #Column(type="datetime", nullable=false)
*/
protected $date_updated;
}
This file is located in a folder named 'models'. If I run the command 'orm:generate-entities models', then it creates new classes inside of '/models/Entities' folder. This only happens because of the 'namespace Entities' declaration. If I run 'orm:schema-tool:create' to try and create my database schema, I get: "Fatal error: Cannot redeclare class Entities\Blob in /Users/rw3iss/Sites/ci/application/models/Entities/Blob.php on line 11".
This is happening because the generated 'models/Entities' classes inherit the namespace from the files they're generated from in the parent 'models' folder, hence the dual class conflict.
Now if I remove the namespace declaration from the parent files, and call generate entities, passing 'models/Entities' as the destination, I get the same file layout. Except then, when trying to use the models in my code:
$blob = new Entities\Blob;
this throws the same error, obviously because there are still two classes with the same name, without a namespace.
I have declared the Entities class loader like this:
$entityClassLoader = new \Doctrine\Common\ClassLoader('Entities', APPPATH.'models');
So my question is:
Is there anyway to generate these entity classes from a basic class (which has my annotations declared for the class and properties), preserving namespaces, so that I can still instantiate them using 'new Entities\Blob'? If there was even a way to tell the generated classes to use a different namespace from the file's they're generated from, that would be fine. I'd like to setup basic properties, and have the 'generate entities' command create my get/set methods for me. It seems that whenever I use namespaces, it will auto-create the classes inside of the namespace subfolders, and then I get the 'cannot redeclare class' error.
Maybe I'm doing something fundamentally wrong...
Thanks for any help!
UPDATE: Solution:
I may have gotten it working by putting the Entities folder side by side with my models folder. If I change the Entities ClassLoader to point to just 'APPPATH', and then instantiate my Entities using 'new Entities\Blob', then that works.
It seems like there is no way to put the Entities folder as a subfolder within the models folder without it complaining in some way. If anyone know of a way to do this, I'd be interested to hear.
i got the same problem. That's because you specify a subfolder in the command.
Just type : "orm:generate-entities ." (without quotes)
"." is meaning actual folder.
I have this working with entities and models in two different subfolders. Here is how i processed :
my files structure :
+ framework (root folder)
index.php
+ entities (model folder)
Formation.php
+ repositories (repositories folder)
FormationRepository.php
+ controllers ( controllers folder)
HomeController.php
in index.php :
require 'vendor/doctrine/common/lib/Doctrine/Common/ClassLoader.php';
$entitiesLoader = new ClassLoader('entities', __DIR__);
$entitiesLoader->setFileExtension('.php'); // not necessary, i think that .php is set by default
$entitiesLoader->register();
// registering entities repositories classloader
$repositoriesLoader = new ClassLoader('entities\repositories', __DIR__);
$repositoriesLoader->setFileExtension('.php');
$repositoriesLoader->register();
here is an entity : (Formation.php)
// Formation.php
<?php
namespace entities;
/**
* #Entity(repositoryClass="entities\repositories\FormationRepository")
* #Table(name="formations")
*/
class Formation
{
....
here is how i use it : (in HomeController.php)
// in HomeController.php
<?php
// if i need it directly :
use entities\Formation;
$formation = new Formation();
// if i want to use it with its repository (and Doctrine)
$formation = $this->getApp()->getDbConnection()->getRepository('entities\Formation')->findOneById(1);
pay attention to "getRepository('entities\Formation')". My mistake was to not specifying the namespace "entities\" before the name of the entity.