Following this blog post I successfully implemented Class-based factories in Laravel.
Initially I put my ModelFactorys in app/some/folder. Everything was totally fine. But I want them in database/factories/classbased, and then this error started;
PHP Fatal error: Cannot declare class Factories\ClassBased\GroupFactory, because the name is already in use in ..root/project/database/factories/classbased/GroupFactory.php on line 18
I have had a good look on SOF and elsewhere about this error, but all the answers seem to be about different reasons/ I can't transpose the answers given to my situation.
I have tried renaming my classes to something totally unique (as ModelFactory is already a naming format used by Laravel for its standard factories) but I still got the same error. My custom classes seem to be re-declaring and I don't know why.
This is what I have for my custom class:
<?php
// database/factories/classbased/GroupFactory.php
namespace Factories\ClassBased;
class GroupFactory
{
// stuff //
public function facilitatedBy(TeamMember $teamMember)
{
$this->facilitator = $teamMember;
return $this;
}
This is what I have in my test:
<?php
namespace Tests\Feature;
use XYZ;
use Facades\Factories\ClassBased\GroupFactory;
class ClassBasedGroupFactoryTest extends TestCase
{
use RefreshDatabase, SetUpRolesAndPermissions, WithFaker;
public function setUp() : void
{
parent::setUp();
$this->setUpRolesAndPermissions();
}
/** #test */
public function it_can_set_the_facilitator()
{
$facilitator = $this->createTeamMemberWithRoleOf('facilitator');
$group = GroupFactory::facilitatedBy($facilitator)->create();
$this->assertEquals($facilitator->id, $group->facilitator->id);
}
/** #test */
public function another_test()
{
$x = 'y';
$group = GroupFactory::someThing($x)->create();
$this->assertEquals($x, $group->theThing);
}
And I have this in my composer.json:
"autoload": {
"files": [
// files
],
"psr-4": {
"App\\": "app/"
},
"classmap": [
"database/seeds",
"database/factories",
"database/factories/classbased"
]
},
I would expect to be able to use the class without issue, as I did when it was in the App namespace. But when I refactored to this then the errors started.
What do I need to do to fix this?
I think that the issue is not existing anymore, but I'm adding a possible solution for those who might stumble across this thread.
Use a psr-4 autoloader inside composer.json and put the factories on same level and not in a subdirectory of factories.
"autoload": {
"psr-4": {
"App\\": "app/",
"Database\\Classbased\\": "database/classbased/"
},
"classmap": [
"database/seeds",
"database/factories"
]
},
Update your files to reflect the proper namespace and directory structure.
<?php // database/classbased/GroupFactory.php
namespace Factories\ClassBased;
class GroupFactory {
Sidenote: I'm still puzzled why using a subdirectory inside factories/ was not working for me.
Related
I was wondering if it's possible somehow to automatically load all Auth::user() relationships.
Auth::user() returns an instance of my App\Models\Auth\Usuario.php, and inside Usuario.php class I have some relationships with another models.
The way I'm doing it now manually loads the relations with $user->load('relation') but I need to do it in every request.
I was thinking to do something like this in my base Controller:
public function __construct()
{
$user = Auth::user();
$this->relation = $user->load('relation');
}
But It's not exactly what I'm looking for.
There is another/best way to load all the Auth::user() class relationships? Like middleware or something?
You can use the $with property on your model to declare relationships that should always be eager loaded.
From the docs:
Sometimes you might want to always load some relationships when
retrieving a model. To accomplish this, you may define a $with
property on the model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Book extends Model
{
/**
* The relationships that should always be loaded.
*
* #var array
*/
protected $with = ['author'];
/**
* Get the author that wrote the book.
*/
public function author()
{
return $this->belongsTo('App\Author');
}
}
I'm using a view shared variable set in a middleware, so here is a example
the route:
Route::prefix('accounts')->middleware(['auth', 'profile'])
the middleware (profile) :
view()->share('currentUser', Auth::user()>setRelations(['profile']));
in any view:
$currentUser->profile->description
I am not sure why you are manually loading relations, this should be done within your model?
Anyway to answer your question, i use a helpers.php which I add to composer autoload:-
"autoload": {
"psr-4": {
"App\\": "app/"
},
"classmap": [
"database/seeds",
"database/factories"
],
"files": [
"app/helpers.php"
]
within this helpers file you could decalare custom global methods:-
function current_user()
{
return auth()->user();
}
I'm building a PHP web application with Laravel and am trying to pass a name and email from a form to my database, but it displays this error:
Fatal error: Uncaught Error: Class 'user' not found in
C:\xampp\htdocs\MVC\app\controller\home.php:20 Stack trace: #0
C:\xampp\htdocs\MVC\app\core\app.php(43): home->create('hala',
'hala#yahoo') #1 C:\xampp\htdocs\MVC\public\index.php(4):
app->__construct() #2 {main} thrown in
C:\xampp\htdocs\MVC\app\controller\home.php on line 20
This is the code I'm using for the home page:
class home extends controller
{
public function index($name = '')
{
$this->view('home/index', ['name'=>$user->name]);
}
public function create($username = '', $email = '')
{
user::create([
'username' => $username,
'email'=> $email
]);
}
}
and the model:
use Illuminate\Database\Eloquent\Model as Eloquent;
class user extends Eloquent
{
public $name;
protected $fillable = ['username','email'];
}
What am I doing wrong and how can I fix it?
In your controller code, you need to include the user class:
require_once("user.class.php"); /* or whatever the file is named */
If this is done automatically and the class is in a different namespace, you need to declare your intent to use it in the controller:
use \my\namespace\user;
Or just use the fully qualified class name in your code:
\my\namespace\user::create();
If you use illuminate/database then chances are you are using composer. Why not add a PSR-4 auto load rule and structure your code accordingly. Eg. composer.json might look like this:
{
"name": "acme/acme",
"description": "Acme is this and that",
"type": "project",
"require": {
"php": "^7.2",
"illuminate/database": "^5.7"
},
"autoload": {
"psr-4": {
"Acme\\": "src"
}
},
"license": "proprietary"
}
Runing composer install makes you an vendor/autoloader.php and it is the only file you need to require. You put your own code un the Acme (or whatever you chose) namespace. Eg. You put your user model under src/Model/User.php and add your namespace:
<?php
namespace Acme\Model;
use Illuminate\Database\Eloquent\Model as Eloquent;
class User extends Eloquent
{
public $name;
protected $fillable = ['username','email'];
}
Your main file might look like this..
<?php
// entry point file
require_once('vendor/autoload.php');
use Acme\Model\User;
$user = new User();
// ...
Obviously you would make most logic in some class so this should be quite short.
This might seem obvious to people working on recent projects, but I have seen too many projects that still have a static file including all the classes like we did in the olden days. Move your projects to the 2010s now!
I just figured out how to install and use PHP composer and used it to instal php-sql-query-builder to my project. The system created the vendor folder, etc. however I am having issues using classes within the package. It gives me the following error, any suggestions on how I can fix this?
Fatal error: Uncaught Error: Class 'NilPortugues\Sql\QueryBuilder\Builder\GenericBuilder' not found in D:\Documents\CadetPortal\php\lib\login.class.php on line 15
Login.class.php
require_once ("core.class.php");
require_once ("../../vendor/autoload.php");
use NilPortugues\Sql\QueryBuilder\Builder\GenericBuilder;
class LoginSystem {
private $core;
private $builder;
private $config;
function __construct(){
$this->core = new coreFunctions();
$this->builder = new GenericBuilder();
$this->config = require('core.config.php');
}
//....
}
EDIT
fncregister.php
require_once "../../vendor/autoload.php";
$LoginManager = new \ThomasSmyth\LoginSystem();
echo $LoginManager->Register($_POST["StrSurname"], $_POST["StrForename"], $_POST["StrEmail"], $_POST["StrPassword"], $_POST["DteDoB"], $_POST["StrGender"], $_POST["StrToken"]);
composer.json
{
"require": {
"nilportugues/sql-query-builder": "^1.5"
},
"autoload": {
"psr-4": {
"ThomasSmyth\\": "php/lib/"
}
}
}
Your class source files shouldn't have any require_once statements at all in them. Follow the PSR-4 spec for naming. Put your classes in a namespace to avoid collision with other classes you might include via composer. Then put one class in one file, named the same as the class. For example, the LoginSystem class should be in a file named LoginSystem.php.
namespace MyNamespace;
class LoginSystem
{
...
}
Then set your composer.json to point your namespace to your source directory:
"autoload": {
"psr-4": {
"MyNamespace\\": "src/"
}
},
Now, your main app invoker or front controller should be the only place that includes the autoloader:
require_once 'vendor/autoload.php';
$login = new \MyNamespace\LoginSystem();
...
I am new to Laravel. I want use some Own Functions. Where do Write the Function.
<?php function userrole1($roleid) {
$userrole=DB::table('roles')->where('id', '=', $roleid)->get();
?>
#foreach($userrole as $val)
<?php echo $val->role_title; ?>
#endforeach
<?php
}
?>
New Way to add Helpers
1: I created folder app/Helpers
2: In app/Providers I created new provider file HelperServiceProvider.php
3: In this file I registered all helpers classes I need
$this->app->bind('dateHelper', function()
{
return new \App\Helpers\DateHelper;
});
In config/app.php I added this new provider
'App\Providers\HelperServiceProvider',
Use This helper function dateHelper
Old Way
Create a helpers.php file in your app folder and load it up with composer:
"autoload": {
"classmap": [
...
],
"psr-4": {
"App\\": "app/"
},
"files": [
"app/helpers.php" // <---- ADD THIS
]
},
After adding this run composer dump-autoload command in cmd
You need to create and register your own helpers file:
http://laravel-recipes.com/recipes/50/creating-a-helpers-file
After that you'll be able to use custom helpers (functions) in your app.
Just make a function in the model class and include model and call it from the controller as pass from there to the view using variable. thats it.
In Model User(you can make any):
public function userrole1($roleid) {
$userrole=DB::table('roles')->where('id', '=', $roleid)->get();
return $userrole
}
In Controller:
use App\User
public function __construct(User $user){
$this->user_model = $user;
}
public function index(){
$userRole = $this->user_model->userrole1()
return view('admin/index', ['userRole' => $userRole]);
}
Composer.json
"autoload": {
"classmap": [
"database"
],
"files": [
"vendor/koraktor/steam-condenser/lib/steam-condenser.php"
],
"psr-4": {
"App\\": "app/"
}
},
HomeController
public function index()
{
$server = new SourceServer('80.67.11.46:27025');
try {
$server->rconAuth('abc123');
echo $server->rconExec('status');
}
catch(RCONNoAuthException $e) {
trigger_error('Could not authenticate with the game server.',
E_USER_ERROR);
}
}
I have updated the composer after adding, dump-autoload and tried all the solutions i can find with namespaces and so on.
But can't still use the steam condenser classes, any solution for this ?
The error Class 'App\Http\Controllers\SourceServer' not found denotes the fact that you're inside the App\Http\Controllers namespace and as such it will try to find the SourceServer class within that namespace. Prepend \ to your class name to call it in a global context:
$server = new \SourceServer('80.67.11.46:27025');
Or add this after the namespace declaration at the top of your controller:
use SourceServer;
And remove the class mapping from composer.json because it's not needed. You can read up more on how namespaces work in the PHP Namespaces Documentation.