i'm trying to create a product which belongs only to one order. That order id i'm taking with me to create form, but don't know how to pull it to store function.
Updated files:
ProductController:
use Illuminate\Http\Request;
use App\Order;
use App\Product;
use Illuminate\Support\Facades\Route;
class ProductController extends Controller
{
public function create(Order $order){
return view('order.product-create', compact($order));
}
public function store(Order $order, Request $request){
$this->validate($request, [
'name'=>'required',
'drawing'=>'nullable|file',
'3d_file'=>'nullable|file',
'quantity'=>'integer',
'unit_price'=>'required',
'discount'=>'nullable'
]);
$order->products()->create($request->all());
session()->flash('product-created', 'New product was added successfully');
return redirect()->route('order.view');
}
}
Route:
Route::get('/order/{order}/product/create', 'ProductController#create')->name('product.create');
Route::post('/order/{order}/product', 'ProductController#store')->name('product.store');
view.blade.php ---> link to product create form
Add new product
product.create.blade.php ---> fragment to method action
action="{{route('product.store', ['order' => $order])}}"
so with this at the moment, i can't get in to product-create.blade.php with error $order is undefined
Dynamic parameters are defined as curly braces in your route file in routes/web.php or routes/api.php
// routes/web.php
Route::get('/order/{order}/product/create', 'ProductController#create')->name('product.create');
Route::post('/order/{order}/product', 'ProductController#store')->name('product.store');
Use Route model binding in ProductController.php to have Laravel resolve the order out of the container.
// ProductController.php
use App\Order;
use App\Product;
use Illuminate\Http\Request;
class ProductController extends Controller
{
public function create(Order $order)
{
// Only get here if laravel resolves the $order model
return view('order.product-create', compact('order'));
}
public function store(Order $order, Request $request)
{
// Only get here if laravel resolves the $order model
//validation
$this->validate($request, [
'name' => 'required',
'drawing' => 'nullable|file',
'3d_file' => 'nullable|file',
'quantity' => 'integer',
'unit_price' => 'required',
'discount' => 'nullable'
]);
// Create related Product model and associate it with the Order model.
// https://laravel.com/docs/7.x/eloquent-relationships#the-create-method
//
// Need to allow for mass assignment in the Product.php model
// https://laravel.com/docs/7.x/eloquent#mass-assignment
$order->products()->create($request->all());
// Flash to session and redirect after creating
session()->flash('product-created', 'New product was added successfully');
return redirect()->route('order.view');
}
}
view.blade.php
Add new product
product.create.blade.php
action="{{route('product.store', ['order' => $order])}}"
The way i understood, you want to pass the Order ID from your create form to your controller function, and based on that you want to save your form data.
You can pass your Order ID to your POST route by
{{ route('route_name', ['order_id' => $order->id]) }}
and your Route in web.php would be
Route::post('/order/{order_id}/product/create', 'ProductController#store')->name('route_name)
Create Method with Relationship
Relationship Documentation
You can accept your parameters passed with in your controller function by
public function store($order_id)
{
//validation
//save function
$order = App\Order::findOrFail($order_id); //Fails if the passed id is not present in DB
// Assuming you have one to one relationship
// Product() is the relationship you declare in your model
$product = $order->Product()->create([
'your_columns' => 'values',
]);
// redirect after save
}
Edit : Updated Question
use Illuminate\Http\Request;
use App\Order;
use App\Product;
use Illuminate\Support\Facades\Route;
class ProductController extends Controller
{
public function create(Order $order){
// you are receiving the Order instance by the Order ID (primary key defined)
return view('order.product-create', compact($order));
}
public function store(Order $order, Request $request){
$this->validate($request, [
'name'=>'required',
'drawing'=>'nullable|file',
'3d_file'=>'nullable|file',
'quantity'=>'integer',
'unit_price'=>'required',
'discount'=>'nullable'
]);
$order->products()->create($request->all());
session()->flash('product-created', 'New product was added successfully');
return redirect()->route('order.view');
}
}
and your Routes
// order = order id which is passed to the controller Order $order variable instance
Route::get('/order/{order}/product/create', 'ProductController#create')->name('product.create');
Route::post('/order/{order}/product/create', 'ProductController#store')->name('product.store');
Your form POST
// You can pass the ID of the order result you receive from your `create` function
<form action = "{{ route('product.store',['order' => $order->id]) }}" ... >
Related
I want to assign an organization to a user but what happens in my code is that when I create a new organization and it's ID is 1, it automatically assigns itself to user ID 1 also.
This is my AssignOrgToUser controller:
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\organizations;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class AssignOrgToUserController extends Controller
{
public function assignOrg(Request $request, $id)
{
$users = User::find($id);
if(is_null($users)){
return response()->json(["message"=>"User not found!"], 404);
}
$rules=[
'organization'=>'required',
];
$validator = Validator::make($request->all(), $rules);
if($validator->fails()){
return response()->json($validator->errors(),400);
}
$data = $request->validate([
'organization'=>'required',
]);
$orgs = organizations::where('id', '=', $request->organization)->first();
if(is_null($orgs)){
return response()->json(["message"=>"Organization not found!"], 404);
}
$orgs= $users->save();
if($orgs){
return ["result"=>"ORG Added"];
}else{
return ["result"=>"ORG not Added"];
}
// $users->save([$orgs]);
// return response(['message'=>"Organization has beed added", $users]);
}
}
Organization Model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class organizations extends Model
{
public $table = "organizations";
use HasFactory;
protected $guarded = [];
public function users(){
return $this->belongsTo('App\Models\User'); #if column not found indicate the column name
}
}
Any kind of help/suggestions will be greatly appreciated. Thank you!!
Replace this $orgs= $users->save(); with the below code
For update use associate method do like this (in your Case)
$orgs = Organisation::create(['someColumn' => $request->someColumn]);
$orgs->users()->associate($users);
$orgs->save();
for more https://laravel.com/docs/8.x/eloquent-relationships#inserting-and-updating-related-models
It seams like the problem came from you Request URL, you have define you Controller to receive a paramater name id with that I can presume you have define the Route like this
Route::post("/assign_organization/{id}", [AssignOrgToUserController::class, "assignOrg"]);
If the request url contain a user ID which is 1 any time you'll try to create an organization it will be attached to a user which ID is 1. as you are retrieving the user based on the id get from the URL
$user = User::find($id);
If you want to assign an organization with a different User ID, you should pass that User ID in you request body. and that won't consider the URL Body
$user = User::find($request->get("user_id"));
In lumen 8 app I use resources and reading here
https://laravel.com/docs/8.x/eloquent-resources
I try to use “with” method, as I want to add some meta data to any request and I have no
this meta data in returned data :
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
use App\Models\Page As PageModel;
use App\Http\Resources\User as UserResource;
class Page extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
...
'created_at' => $this->created_at,
];
}
public function with($request)
{
\Log::info( '-1 unction with ::' . print_r( 1, true ) ); // I DO NOT SEE THIS LOGGINHG line
return [
'meta' => [
'version'=>getAppVersion()
]
];
}
}
In the referenced docs resource is declared a bit different from ResourceCollection:
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\ResourceCollection;
class UserCollection extends ResourceCollection
{
public function toArray($request)
{
return parent::toArray($request);
}
public function with($request)
{
return [
'meta' => [
'key' => 'value',
],
];
}
}
Could it be the issue and how can fix my resource to get all meta data ?
Updated block:
UserCollection - that is collection https://laravel.com/docs/8.x/eloquent-resources
my collection is Page and I use it in controller as :
namespace App\Http\Controllers;
use Carbon\Carbon;
use App\Models\Page;
use Illuminate\Http\Request;
use App\Http\Resources\Page as PageResource;
use Config;
use App\Http\Requests\PageRequest;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
use Validator;
class PageController extends Controller
{
public function index()
{
$pages = Page
...
->get();
return $this->sendOkResponse(PageResource::collection($pages), '');
}
sendOkResponse defined in Http/Controllers/Controller.php :
class Controller extends BaseController
{
protected $requestData;
public function __construct()
{
$request = request();
$this->requestData = $request->all();
}
public function sendOkResponse($responseResult, $message)
{
$response = [
'success' => true,
'data' => $responseResult,
'message' => $message,
];
return response()->json($response, HTTP_RESPONSE_OK);
}
I suppose PageResource is destroyed at PageController controller index method exit...
Updated block # 2:
After some tests I found that Resource method “with” does not work if collection is returned
and I need to use ->additional in controller like:
return (PageResource::collection($pages))
->additional([
'meta' => [
'version' => getAppVersion()
]
]);
But in cases when I return sinopgle element(ex store method) like
return (new PageResource($page));
method “with” works ok.
That exludes using of wrapper like sendOkResponse.
Is is the only proper way?
Thanks in advance!
Laravel resources are intended to be returned directly from your controller's action method, not as part of an associative array representing JSON.
When wrapping your responses with the sendOkResponse method, the resource is not being returned directly from the method and thus toArray is being called on your resource. The with method on your resources is being ignored.
Try returning the resources directly from your controller's method. Use the additional method when constructing your resources to pass the extra attributes in the response. See: https://laravel.com/docs/8.x/eloquent-resources#adding-meta-data-when-constructing-resources.
If you can control the API contracts, I'd recommend changing them to omit success entirely, this can be derived from the HTTP status code.
I am kinda new to both Laravel and Vue and I am working on a school project. I have been following a guide and trying to develop the product but I have the following problem: in the guide was only possible to do an order with a single product. Using LocalStorage a created a Cart component where you can add several products instead. How do I use axios.post to correctly post the order in the database now?
app/Http/Controllers/OrderController.php:
<?php
namespace App\Http\Controllers;
use App\Models\Order;
use Auth;
use Illuminate\Http\Request;
class OrderController extends Controller
{
public function index()
{
return response()->json(Order::with(['product'])->get(),200);
}
public function store(Request $request)
{
$order = Order::create([
'product_id' => $request->product_id,
'user_id' => Auth::id(),
'quantity' => $request->quantity,
'address' => $request->address
]);
return response()->json([
'status' => (bool) $order,
'data' => $order,
'message' => $order ? 'Order Created!' : 'Error Creating Order'
]);
}
public function show(Order $order)
{
return response()->json($order,200);
}
Resources/JS/views/Checkout.vue (between < script > tag):
placeOrder(e) {
e.preventDefault()
let address = this.address
let product_id = this.product.id
let quantity = this.quantity
axios.post('api/orders/', {address, quantity, product_id})
.then(response => this.$router.push('/confirmation'))
},
App/Http/Models/Order.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Order extends Model
{
use SoftDeletes;
protected $fillable = [
'product_id', 'user_id', 'quantity', 'address'
];
public function user()
{
return $this->belongsTo(User::class, 'user_id');
}
public function product()
{
return $this->belongsTo(Product::class, 'product_id');
}
}
Actually, You can achieve your goal by changing many lines of code instead of using your current code at backend (laravel Model-Controller) and frontend (Vue). I will show you how to do by adding hasMany relationship in your User model structure, then changing saving method at controller, and axios request payload. This method has limitation, you have to post an array of products of the same user ID.
Add hasMany relationship in your User Model. Read this
class User extends Model
{
//add this line
public function order()
{
return $this->hasMany(Order::class);
}
Use createMany function to save multiple rows in your controller. Read this
public function store(Request $request)
{
//use this lines to store array of orders
$user = Auth::user();
$orderStored = $user->order()->createMany($request->data);
//return your response after this line
}
Change your axios payload from vue method
data(){
return {
//add new key data to store array of order
arrayOfOrders:[];
};
},
methods:{
placeOrder(e) {
e.preventDefault()
let address = this.address
let product_id = this.product.id
let quantity = this.quantity
//remark these lines, change with storing to arrayOfOrders data instead of doing post request
//axios.post('api/orders/', {address, quantity, product_id})
//.then(response => this.$router.push('/confirmation'))
this.arrayOfOrders.push({
product_id:product_id,
quantity:quantity,
address:address
});
},
//create new function to make post request and call it from your button
postData(){
let instance = this;
axios.post('api/orders/', {
data:instance.arrayOfOrders
}).then(response => this.$router.push('/confirmation'))
}
}
Thank you for your answer! Just one thing is not so clear.. in my OrderController.php should the final code look something like this?
public function store(Request $request)
{
$user = Auth::user();
$order = $user->order()->createMany([
'product_id' => $request->product_id,
'user_id' => Auth::id(),
'quantity' => $request->quantity,
'address' => $request->address
]);
return response()->json([
'status' => (bool) $order,``
'data' => $order,
'message' => $order ? 'Order Created!' : 'Error Creating Order'
]);
}
I'm trying to build a multiple authentification in laravel with different tables (2 tables) for admin and user. The problème is that the registration and login forms work only with default auth login/register.
I've tried some examples form web tutorials but it didn't work.
HomeController.php:
public function __construct() {
$this->middleware('auth');
}
public function index() {
return view('home');
}
I have added createAdmin function in "Auth/RegisterController.php":
protected function createAdmin(array $data)
{
$this->validator($data->all())->validate();
$admin = Admin::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
return redirect()->intended('login/admin');
}
I have changed email validation rules to:
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'|'unique:admins']
And the route (web.php) is:
Route::post('/register/admin', 'Auth\RegisterController#createAdmin');
When I fill admin register credentials and click register button I get this message:
Symfony\Component\Debug\Exception\FatalThrowableError Too few arguments to function App\Http\Controllers\Auth\RegisterController::createAdmin(), 0 passed and exactly 1 expected
The error is coming from the array $data parameter in your createAdmin() controller method.
Usually, you want to use one of two types of parameters in your controller methods: route parameters or injected dependencies. The $data parameter isn't matching either of those, so Laravel doesn't know to provide it.
If you'd like to access the request (POST) data in the controller, you can either ask for an instance of Illuminate\Http\Request as a parameter:
// Import it at the top of your PHP file
use Illuminate\Http\Request;
// Then your updated method:
public function createAdmin(Request $request)
{
$data = $request->all();
// ...
}
Or, use the request() helper directly:
public function createAdmin()
{
$data = request()->all();
// ...
}
I want to build something like facebook and I have a form where the user can post content but I want to use the same form on different sections, for example: groups, pages, profile.
I have PostController that is a resource that receives the post requests but I need a way to differentiate between sections in order to store the data with the correct section_type and section_id.
// Post Model Post.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
protected $fillable = ['content', 'user_id'];
public function section()
{
return $this->morphTo();
}
public function user()
{
return $this->belongsTo(User::class);
}
public function group()
{
return $this->belongsTo(Group::class);
}
public function page()
{
return $this->belongsTo(Page::class);
}
}
The User.php Model
class User extends Authenticatable
{
public function posts()
{
return $this->morphMany(Post::class, 'section');
}
}
and this is the PostController and store() function where I have only one situation at this moment where a post is stored in section_type App\User, but I need a way to store it in App\Group or App\Page also.
public function store(Request $request)
{
$this->validate(request(),
[
'content' => 'required|min:5',
]);
$user = User::find(Auth::id());
$user->posts()->create([
'content' => $request->content,
'user_id' => Auth::id()
]);
return redirect('/');
}
What do I need to do in PostController.php?
I thought maybe I could use a post request with parameters in the form, like this for posting in groups
<form method="post" action="/?group=1">
or this for posts in pages
<form method="post" action="/?page=1">
And after that use $request->query() to get the section and id. Do you have other ideas?