I have built laravel applications in Laravel 4 and Laravel 5, but I decided this time to write all my tests first, having never previously written tests at all for trivial apps.
Here is my Account class - for illustration
class Account extends Model
{
protected $customer_id;
protected $bookmaker_id;
protected $balance;
protected $profit;
public function __construct($customer_id, $bookmaker_id, $balance, $profit) {
$this->customer_id = $customer_id;
$this->bookmaker_id = $bookmaker_id;
$this->balance = $balance;
$this->profit = $profit;
}
}
So all my unit tests run fine:
My route is set up correctly to the page I want to display
Route::get('/accounts', 'AccountController#index');
but this is where it goes wrong. Actually trying to run a page to get a list of accounts is troublesome. I know there is more to do with the controller class but here is what I have.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use App\Account;
class AccountController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
$accounts = Account::all();
return view('account.index', compact('accounts'));
}
}
Then I get this error -
ErrorException in Account.php line 14:
Missing argument 1 for App\Account::__construct(), called in /Applications/MAMP/htdocs/mb-app/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php on line 665 and defined
Can someone tell me how I should be setting up my controller please? Until I added the __construct() for my unit tests this was all going ok.
Thanks.
By using __construct, it expects arguments any time you initialize it. So instead, you'd use
$accountModel = new Account($customer_id, $bookmaker_id, $balance, $profit);
$accounts = $accountModel->all();
If you want to use those variables for creating a new model, look into $fillable.
Related
I've created a Laravel project on Laravel 9.20.0 and I'm attempting to use an API wrapper for Linnworks I found on Github (https://github.com/booni3/linnworks-laravel) within my project. I'm okay with raw PHP but admittedly a complete beginner when it comes to Laravel and object oriented PHP.
In my /routes/web.php file I have:
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\TestController;
Route::get('test', [TestController::class, 'test']);
In /app/Http/Controllers/TestController.php I have:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Services\OrderService;
class TestController extends Controller
{
protected $orderService;
/**
* Instantiate a new controller instance.
*
* #return void
*/
public function __construct(OrderService $orderService)
{
$this->orderService = $orderService;
}
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function test()
{
$this->orderService->calculateProfit();
}
}
In /app/Services/OrderService.php I have:
<?php
namespace App\Services;
use Linnworks;
class OrderService {
public function __construct()
{
}
public function calculateProfit()
{
$this->getOrder();
return;
}
public function getOrder()
{
$order = Linnworks::Orders()->GetOrdersByNumOrderId(777678);
echo "<pre>";
print_r($order);
echo "</pre>";
return;
}
}
At this point, I'm just trying to figure out the correct way to use the Linnworks API Wrapper from GitHub within my service class and get it to return something from the Linnworks platform.
I have input the correct API details in the .env file but I'm clearly doing something wrong or missing something obvious (likely due to my lack of experience with object oriented PHP and Laravel) and I'm getting the following error when I load my url /test/:
Booni3\Linnworks\Linnworks::__construct(): Argument #1 ($config) must be of type array, string given, called in /home/username/laravel-projects/project-name/vendor/booni3/linnworks-laravel/src/LinnworksServiceProvider.php on line 49
According to the GitHub readme, usage is as simple as:
$orders = Linnworks::Orders()->getOpenOrders(
25,
1,
null,
null,
'e41b4701-0885-430d-9623-d840d9d46dd6',
null);
Any help or pointers in the right direction will be hugely appreciated as I've hit a bit of a wall.
Thanks in advance
I am using Laravel Filament and made a Resource for User model which works fine.
I have a is_admin field in users table which return 0 and 1. I need users with is_admin = 0 but for now , i am getting all of them.
Can i add a where condition in filament to get only required fields.
The proper way to add additional where conditions with the built-in eloquent query are as follows:
public static function getEloquentQuery(): Builder
{
return static::getModel()::query()->where('is_admin', 1);
}
A bit late for the answer, bit here's an in depth guide.
There are two ways to go about it
#1 Pre-filtering query inside the resource
Inside your resource, override the following method:
public static function getEloquentQuery(): Builder
{
return parent::getEloquentQuery()->where('is_admin', 0);
}
#2 Global Scope
Filament uses the eloquent interface, so applying a global scope will do the job aswell.
First, create a global scope class inside App\Models\Scopes\ (not a required path, only a suggestion):
<?php
namespace App\Models\Scopes;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;
class AncientScope implements Scope
{
public function apply(Builder $builder, Model $model)
{
$builder->where('is_admin', 0);
}
}
Then, modify your user model to apply the scope:
<?php
namespace App\Models;
use App\Models\Scopes\AncientScope;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* The "booted" method of the model.
*
* #return void
*/
protected static function booted()
{
static::addGlobalScope(new AncientScope);
}
}
you can put ->where('role', '0') after return nameModal::query() at getTablequery(). \
like this
return nameModal::query()->where('role', '0');
Yes you can. You can extend getEloquentQuery() function at related resource class.Since you are talking about User model you can add above function as in the below code example to UserResource.php.
public static function getEleouentQuery () {
return User::where('is_admin',0);
}
Check this for more
I have controller name as 'CashFlowdata'. In controller I am having code that is :
namespace App\Modules\CashFlowdata\Controllers;
use App\Http\Controllers\Controller;
use App\Modules\CashFlowdata\Models\CashModel;
use App\Modules\CashFlowdata\Lcurd\CashFlowdataLcurd;
use Auth, Womp, Graphs, Projects, Input , Permissions, LcrudForm, LcrudTable, Redirect, Session, Meta;
class CashFlowdataController extends Controller
{
private $lcrud;
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct() {
$this->middleware('auth');
$this->lcrud = new CashFlowdataLcurd();
}
}
But in that I am getting error for
Class 'App\Modules\CashFlowdata\Lcurd\CashFlowdataLcurd' not found
But the file is there and that is with the same name.
If class and file have the same name (case sensitive), maybe you need a
composer dump-autoload
PS: Check 'lcurd' vs 'lcrud'
In a right pickle with phpunit. I currently have a test class for a resource route with 9 tests in it. All but two of these tests pass, ironically what should be the two simplest; the tests for articles.index and articles.show (the last 2 tests in the code below).
<?php
namespace Tests\Feature;
use App\Article;
use Tests\TestCase;
use App\User;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
use DB;
class ArticleTest extends TestCase
{
use RefreshDatabase;
// runs before any of the tests
protected function setUp(): void
{
parent::setUp();
// run tests without language(locale) middleware
$this->withoutMiddleware(\App\Http\Middleware\Language::class);
}
/** #test */
public function unauthenticated_users_can_not_access_create()
{
$this->get('/articles/create')->assertRedirect('/login');
}
/** #test */
public function admin_users_can_access_edit()
{
$article = factory(Article::class)->create();
$record = DB::table('articles')->where('id', $article->id)->first();
$user = factory(User::class)->create();
$user->isAdmin = 1;
$this->actingAs($user);
$this->get('/articles/' . $record->slug . '/edit?locale=en')->assertOK();
}
/** #test */
public function authenticated_but_not_admin_users_can_not_access_create()
{
$this->actingAs(factory(User::class)->create());
$this->get('/articles/create')->assertRedirect('home');
}
/** #test */
public function admin_can_access_create()
{
$user = factory(User::class)->create();
$user->isAdmin = 1;
$this->actingAs($user);
$this->get('/articles/create')->assertOk();
}
/** #test */
public function can_store_an_article()
{
$article = factory(Article::class)->create();
$record = DB::table('articles')->where('id', $article->id)->first();
$this->assertDatabaseHas('articles', ['slug' => $record->slug]);
}
/** #test */
public function admin_can_access_articles_admin_index()
{
$user = factory(User::class)->create();
$user->isAdmin = 1;
$this->actingAs($user);
$this->get('/admin/articles')->assertOk();
}
/** #test */
public function admin_can_delete_article_and_it_is_removed_from_the_database()
{
$user = factory(User::class)->create();
$user->isAdmin = 1;
$this->actingAs($user);
$article = factory(Article::class)->create();
$this->assertDatabaseHas('articles', ['slug' => $article->slug]);
$record = DB::table('articles')->where('id', $article->id)->delete();
$this->assertDatabaseMissing('articles', ['slug' => $article->slug]);
}
/** #test */
public function can_see_article_index_page()
{
$this->get('/articles')->assertOK();
}
/** #test */
public function can_only_access_articles_made_visible()
{
$article = factory(Article::class)->create();
$article->displayStatus = 2;
$this->assertDatabaseHas('articles', ['slug' => $article->slug]);
$this->get('/articles/' . $article->slug)->assertRedirect('/articles');
}
}
The test can_see_article_index_page should return a 200 status code yet it 404's and can_only_access_articles_made_visible should be a redirect status code yet 404's as well.
SEEN HERE
My application is multi-lingual, using the spatie/translatable package and I'm unsure if it's that that is interfering (doesn't really make sense for it to be as the withoutMiddleware line in setUp should prevent this) or something else entirely (i.e my stupidity). My app is built with Laravel 5.8, and I am running phpunit 7.5.
EDIT I found out the error was due to some specific rows not existing in my test database, where in my controller it would fail if it couldn't find them. By adding the line $this->withoutExceptionHandling() to the failing tests it told me this information.
Since all your routes are working but /articles that means that something is not ok with your routes.
You added this route lately: Every time you create a new route or make any changes in the route files of laravel you should run php artisan config:cache command.
I am pretty sure it's not a conflict in routes because of a variable {}, since the status code is a clear 404 meaning that no controller is even accessed that's why i won't elaborate further on possible routing conflicting issues.
If the error persists though get your route at the very top of your routes file and see if it works there. If that's the case that means that one of your routes, overlaps it.
A quick fix to that is to order your static naming routes above the routes using variables for example:
/articles
/{articles}
If you reverse above order your /articles route will never be accessed. This is a case of naming route conflicts.
I'm building an application, now i'm created a helper
class Students{
public static function return_student_names()
{
$_only_student_first_name = array('a','b','c');
return $_only_student_first_name;
}
}
now i'm unable to do something like this in controller
namespace App\Http\Controllers;
class WelcomeController extends Controller
{
public function index()
{
return view('student/homepage');
}
public function StudentData($first_name = null)
{
/* ********** unable to perform this action *********/
$students = Student::return_student_names();
/* ********** unable to perform this action *********/
}
}
this is my helper service provider
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class HelperServiceProvider extends ServiceProvider
{
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
foreach(glob(app_path().'/Helpers/*.php') as $filename){
require_once($filename);
}
}
}
i event added it as an alias in config/app.php file
'Student' => App\Helpers\Students::class,
Try putting use App\Helpers\Student; at the top of your controller beneath the namespace delcaration:
namespace App\Http\Controllers;
use App\Helpers\Student;
class WelcomeController extends Controller
{
// ...
Look more into PHP namespaces and how they are used, I believe you may have a deficient understanding about them. Their only purpose is to make so you can name and use two classes with the same name (e.g. App\Helpers\Student vs maybe App\Models\Student). If you needed to use both of those classes inside of the same source file, you can alias one of them like this:
use App\Helpers\Student;
use App\Models\Student as StudentModel;
// Will create an instance of App\Helpers\Student
$student = new Student();
// Will create an instance of App\Models\Student
$student2 = new StudentModel();
You do not need to have a service provider for this, just the normal language features. What you would need a service provider for is if you wanted to defer the construction of your Student object to the IoC:
public function register()
{
$app->bind('App\Helpers\Student', function() {
return new \App\Helpers\Student;
});
}
// ...
$student = app()->make('App\Helpers\Student');
You should never have to include or require a class file in laravel because that is one of the functions that composer provides.
You do not need a service provider to make it works. Just lets the Students class as you did:
class Students{
public static function return_student_names()
{
$_only_student_first_name = array('a','b','c');
return $_only_student_first_name;
}
}
all its methods should be static
You added the Facade correctly:
'Student' => App\Helpers\Students::class,
Finally, looks like your problem is caused by forgetting a backslash at facade name. Uses \Students instead of Students:
public function StudentData($first_name = null)
{
$students = \Student::return_student_names();
}
When using a facade, it is not necessary makes nay include, the facades were made to avoid complex includes in everywhere.