I'm building a laravel application, and I've created a FakerServiceProvider to populate factories for testing and local dev.
<?php
namespace App\Providers;
use Faker\Factory;
use Faker\Generator;
use Faker\Provider\en_GB\Address;
use Faker\Provider\en_GB\Person;
use Faker\Provider\en_GB\PhoneNumber;
use Illuminate\Contracts\Support\DeferrableProvider;
use Illuminate\Support\ServiceProvider;
/**
* Class FakerServiceProvider
* #package App\Providers
*/
class FakerServiceProvider extends ServiceProvider implements DeferrableProvider
{
/**
*
*/
public function register()
{
$this->app->singleton(Generator::class, function ($app) {
$factory = Factory::create('en_GB');
$factory->addProvider(Person::class);
$factory->addProvider(Address::class);
$factory->addProvider(PhoneNumber::class);
return $factory;
});
}
/**
* #return array
*/
public function provides()
{
return [Generator::class];
}
}
I have created an address factory:
<?php
use App\Address;
use App\Country;
$factory->define(Address::class, function (Faker\Generator $faker) {
return [
'line_1' => $faker->secondaryAddress,
'line_2' => $faker->streetAddress,
'town' => $faker->city,
'county' => $faker->county,
'country_id' => factory(Country::class)->make()->id,
'postcode' => $faker->postcode,
'phone' => $faker->phoneNumber,
];
});
When I try to use this factory I get the following error:
ErrorException: call_user_func_array() expects parameter 1 to be a valid callback, non-static method Faker\Provider\Address::streetAddress() should not be called statically
I have checked the source for the Faker library and there is a streetAddress method here
I have tried calling both $faker->streetAddress and $faker->streetAddress()with no luck. I would expect$faker->streetAddressto produce something like ` or something similar.
Can anyone shed a bit of light on this for me
Removing the added providers in the Faker Service Provider fixed the issue
Related
I am trying to add a shopping cart function to my Laravel application. I installed darryldecode/laravelshoppingcart package from GitHub and have been following instructions in these two websites.
TECHPOOL-Create a Shopping Cart with Laravel 6
LARASHOUT-Laravel E-Commerce Application Development – Checkout
I was able to create most of the shopping cart function with the first website but it didn't cover checkouts and placing orders so I found the second website.
The problem is that the contract file is not working. Here is the error I got.
Illuminate\Contracts\Container\BindingResolutionException
Target [App\Contracts\OrderContract] is not instantiable while building [App\Http\Controllers\CheckoutController].
http://localhost:8000/checkout
Where I use the contract file is in the checkout process witch is explained in the second website. I made few changes in the codes so that it will be consistent with the first website but mostly I followed what the website says.
Here are the codes that are mentioned in the error.
OrderContract.php
<?php
namespace App\Contracts;
interface OrderContract
{
public function storeOrderDetails($params);
}
CheckoutController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Contracts\OrderContract;
use App\Http\Controllers\Controller;
class CheckoutController extends Controller
{
protected $orderRepository;
public function __construct(OrderContract $orderRepository)
{
$this->orderRepository = $orderRepository;
}
public function getCheckout()
{
return view('checkout');
}
public function placeOrder(Request $request)
{
// Before storing the order we should implement the
// request validation which I leave it to you
$order = $this->orderRepository->storeOrderDetails($request->all());
dd($order);
}
}
OrderRepository.php
<?php
namespace App\Repositories;
use Cart;
use App\Models\Order;
use App\Product;
use App\Models\OrderItem;
use App\Contracts\OrderContract;
class OrderRepository extends BaseRepository implements OrderContract
{
public function __construct(Order $model)
{
parent::__construct($model);
$this->model = $model;
}
public function storeOrderDetails($params)
{
$order = Order::create([
'order_number' => 'ORD-' . strtoupper(uniqid()),
'status' => 'pending',
'grand_total' => Cart::getSubTotal(),
'item_count' => Cart::getTotalQuantity(),
'table_number' => $params['table_number'],
'name' => $params['name'],
'notes' => $params['notes']
]);
if ($order) {
$items = Cart::getContent();
foreach ($items as $item) {
// A better way will be to bring the product id with the cart items
// you can explore the package documentation to send product id with the cart
$product = Product::where('name', $item->name)->first();
$orderItem = new OrderItem([
'product_id' => $product->id,
'quantity' => $item->quantity,
'price' => $item->getPriceSum()
]);
$order->items()->save($orderItem);
}
}
return $order;
}
}
RepositoryServiceProvider.php
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Contracts\OrderContract;
use App\Repositories\OrderRepository;
class RepositoryServiceProvider extends ServiceProvider
{
protected $repositories = [
OrderContract::class => OrderRepository::class,
];
/**
* Register services.
*
* #return void
*/
public function register()
{
foreach ($this->repositories as $interface => $implementation) {
$this->app->bind($interface, $implementation);
}
}
/**
* Bootstrap services.
*
* #return void
*/
public function boot()
{
//
}
}
I'm not really familiar with the contract concept since I only started learning Laravel recently and I'm completely lost here. Maybe the problem is that I haven't created another file that is necessary or maybe something else.
Any help would be appreciated as I have tried multiple methods with no success.
Thank you in advance.
Yes, this is expected...your contract should point to a Solid class else it's going to fail while trying to resolve it out of the container. So this is what you should do:
Create a class that implements that trait.
Go to your AppServiceProvider and bind it to that contract like this:
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
//
$this->app->bind(\App\Contracts\OrderContract::class, App\Repositories\ClassImplementingOrderContract::class);
}
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
//
}
}
this should fix your problem.
This error could caused even if you have forget to add "RepositoryServiceProvider" into "config/app.php" 's serviceProviders array.
Currently working on an Excel import functionality. I want to import the Excel sheet and display its information on another page using a foreach loop. However it seems to be rather hard for some reason. When I die and dump the collection data (used this because import would error) it shows everything correctly. The data in the spreadsheet is where it should be. So I feel that is fine. However I cannot get it inserted into my database for some odd reason. I have a header row so I use the WithHeaderRow functionality.
DataImport class:
<?php
namespace App\Imports;
use App\Data;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Imports\HeadingRowFormatter;
HeadingRowFormatter::default('none');
class DataImport implements ToModel, WithHeadingRow
{
/**
* #param array $row
*
* #return \Illuminate\Database\Eloquent\Model|null
*/
public function model(array $row)
{
return new Data([
'cliëntnummer' => $row['clientnummer'],
'zoeknaam' => $row['zoeknaam'],
'naam' => $row['naam'],
'omschrijving' => $row['omschrijving'],
'plaats' => $row['plaats'],
'week' => $row['week'],
'vennoot' => $row['vennoot'],
'relatiebeheerder' => $row['relatiebeheerder'],
'samensteller' => $row['samensteller'],
'ADVer' => $row['adver'],
'cliëntgroepcode' => $row['clientgroepcode'],
'accountant' => $row['accountant'],
'samenstellen' => $row['samenstellen'],
'ADV jaarwerk' => $row['ADVJaarwerk'],
'periodieke ADV' => $row['periodiekeADV'],
'fiscaliteiten' => $row['fiscaliteiten'],
]);
}
}
Datacontroller.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Imports\DataImport;
use Maatwebsite\Excel\Facades\Excel;
use App\Http\Controllers\Controller;
class DataController extends Controller
{
public function index(){
return view('importeren');
}
public function import(Request $request){
$datas = Excel::toCollection(new DataImport(), $request->file('import_file'));
dd($datas);
return redirect()->route('/home');
}
}
Data Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Data extends Model
{
protected $fillable = [
'id', 'cliëntnummer', 'zoeknaam', 'naam', 'omschrijving', 'plaats', 'week', 'vennoot', 'relatiebeheerder', 'samensteller', 'ADVer', 'cliëntgroepcode', 'accountant', 'samenstellen', 'ADV jaarwerk', 'periodieke ADV', 'fiscaliteiten',
];
}
Spreadsheet data:
Database table layout:
Datadump results:
If I left anything out feel free to tell me. I hope this is sufficient.
Turns out I forgot to reference my datamodel in the file, after finalizing the code of my controller like below it now works (almost) seamlessly.
<?php
namespace App\Imports;
use App\Data;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Imports\HeadingRowFormatter;
HeadingRowFormatter::default('none');
class DataImport implements ToModel, WithHeadingRow
{
/**
* #param array $row
*
* #return \Illuminate\Database\Eloquent\Model|null
*/
public function model(array $row)
{
return new Data([
'cliëntnummer' => $row['Cliëntnummer'],
'zoeknaam' => $row['Zoeknaam'],
'naam' => $row['Naam'],
'omschrijving' => $row['Omschrijving'],
'plaats' => $row['Plaats'],
'week' => $row['Week'],
'vennoot' => $row['Vennoot'],
'relatiebeheerder' => $row['Relatiebeheerder'],
'samensteller' => $row['Samensteller'],
'ADVer' => $row['ADVer'],
'cliëntgroepcode' => $row['Cliëntgroepcode'],
'accountant' => $row['Accountant'],
'samenstellen' => $row['Samenstellen'],
'ADVJaarwerk' => $row['ADVJaarwerk'],
'PeriodiekeADV' => $row['PeriodiekeADV'],
'fiscaliteiten' => $row['Fiscaliteiten'],
]);
}
}
Since I am developing package, so I put my factories to custom path like this:
-- app
-- packages
-----mockizart
-------blog
---------database
--------------factories
----------------- PageModelFactory.php
---------src
this is how i load factory in my service provider (I already make sure the path is correct by clicking it on phpstorm):
function boot()
{
Factory::construct($this->app->make(\Faker\Generator::class), __DIR__."/../database/factories");
}
this is my page model factory (I already made sure this file was really loaded):
<?php
/** #var \Illuminate\Database\Eloquent\Factory $factory */
use Mockizart\Blog\Dodols\PageModel;
use Faker\Generator as Faker;
$factory->define(PageModel::class, function (Faker $faker) {
return [
'name' => "retretre",
'slug' => "retretret",
'type' => 0,
'category' => 0,
'tags' => "",
'content' => "",
];
});
and this is my script test :
use Mockizart\Blog\Dodols\PageModel;
.....
.....
/** #test */
public function edit_page()
{
dd(PageModel::find(1)); <-- this return was NULL so I think my class and namespace does exist.
factory(PageModel::class)->make(); <-- this cause error "unable to locate factory......"
$response = $this->get('/blog/page/edit/15');
$response->assertStatus(200);
}
so if you are using orchestra\Testbench, the correct way to load custom factories is in the setUp() method of your Test class or TestCase NOT in your Service Provider.
the code would be like this:
class TestCase extends \Orchestra\Testbench\TestCase
{
public function setUp(): void
{
parent::setUp();
// additional setup
$this->loadMigrationsFrom(__DIR__ . '/../database/migrations');
$this->withFactories(__DIR__.'/../database/factories');
}
protected function getPackageProviders($app)
{
return BlogServiceProvider::class;
}
}
I am running a unit test to check that
View page exists
AssertSee that text appears on the page and with a string limit
I am getting an invalid argument exception:
1) Tests\Feature\ViewAllPostTest::testCanViewAllPosts
InvalidArgumentException: You requested 1 items, but there are only 0 items available.
C:\projects\car-torque-laravel\vendor\laravel\framework\src\Illuminate\Support\Arr.php:472
C:\projects\car-torque-laravel\vendor\laravel\framework\src\Illuminate\Support\Collection.php:1486
C:\projects\car-torque-laravel\database\factories\PostFactory.php:12
C:\projects\car-torque-laravel\vendor\laravel\framework\src\Illuminate\Database\Eloquent\FactoryBuilder.php:274
C:\projects\car-torque-laravel\vendor\laravel\framework\src\Illuminate\Database\Eloquent\FactoryBuilder.php:292
C:\projects\car-torque-laravel\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Concerns\GuardsAttributes.php:122
C:\projects\car-torque-laravel\vendor\laravel\framework\src\Illuminate\Database\Eloquent\FactoryBuilder.php:300
C:\projects\car-torque-laravel\vendor\laravel\framework\src\Illuminate\Database\Eloquent\FactoryBuilder.php:219
C:\projects\car-torque-laravel\vendor\laravel\framework\src\Illuminate\Database\Eloquent\FactoryBuilder.php:178
C:\projects\car-torque-laravel\tests\Feature\ViewAllPostTest.php:19
My source code is as follows:
Test Function
namespace Tests\Feature;
use App\Post;
use Tests\TestCase;
class ViewAllPostTest extends TestCase
{
/**
* #group posts
*
* #return void
*/
public function testCanViewAllPosts()
{
//arrange
$post = factory(Post::class)->create();
//action
$response = $this->get('/posts');
//assert
$response->assertStatus(200);
$response->assertSee($post->body);
$response->assertSee(str_limit($post->body));
}
}
Factory Class
use App\Post;
use App\User;
use Faker\Generator as Faker;
$factory->define(Post::class, function (Faker $faker) {
return [
'body' => $faker->text,
'user_id' => User::all()->random()->id,
'created_at' => now(),
'updated_at' => now(),
];
});
'user_id' => User::all()->random()->id,
In the above line of your factory, you want random id form your users table. But have you created any User before running the test. At least a user should be created before creating post using post factory.
laravel5.2,I create a UserRequest.php under Requests directory,but in controller,public function add(UserRequest $request) show error,but use public function add(Request $request) is normal.
UserRequest
namespace App\Http\Requests;
use App\Http\Requests\Request;
class UserRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'user_sn' => 'required|unique',
'user_name' => 'required',
'email' => 'required|unique',
'password' => 'required',
];
}
}
UserController
namespace App\Http\Controllers;
use App\Http\Requests\UserRequest;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
class UserController extends Controller
{
public function add(UserRequest $request)
{
if ($request->get('dosubmit')) {
$validator = Validator::make($request->all(), $request
->rules(), $request->messages());
if ($validator->fails()) {
return redirect('user/add')->withErrors($validator)
->withInput();
}
}
$corporation_list = DB::table('corporation')->get();
$department_list = DB::table('department')->get();
return view('user.add', ['corporation_list' => $corporation_list, 'department_list' => $department_list]);
}
}
Route
Route::group(['middleware'],function (){
Route::any('user/add',['as'=>'user.add','uses'=>'UserController#add']);
});
There are usually 2 reasons you could be having this issue.
You've not added the use statement for the UserRequest.
At the top of your controller (above the class) add:
use App\Http\Requests\UserRequest
assuming that is the correct namespace.
You may need to run composer dump-autoload to make sure the class has been added to the autoloader.
Edit
Firstly, replace the add() method with the following methods:
public function create()
{
$corporation_list = DB::table('corporation')->get();
$department_list = DB::table('department')->get();
return view('user.add', compact('corporation_list', 'department_list'));
}
public function store(UserRequest $request)
{
// If you get to this point the validation will have passed
// Process the request
}
Then change your routes from:
Route::any('user/add',['as'=>'user.add','uses'=>'UserController#add'])
to:
Route::get('user/add', ['as' => 'user.add', 'uses' => 'UserController#create']);
Route::post('user/add', ['as' => 'user.store', 'uses' => 'UserController#store']);
Obviously, feel free to change the as in the Routes to whatever, they should unique though.
Lastly, I would suggest looking at Resource Controllers which is a RESTful approach.
The problem is that you have not identified UserController that you are using UserRequest file
use App\Http\Requests\UserRequest
It will solve the problem