Laravel One to many CRUD Example - php

I am new to Laravel. I want to insert data to certain master detail tables with Laravel4. I searched all over the internet and could not find a proper solution.
I have two (plus one) tables as shown below.
PO_HEADER
PO_HEADER_ID
SUBJECT
PO_DATE
PO_DETAIL
PO_DETAIL_ID
PO_HEADER_ID
DESCRIPTION
AMOUNT
QTY
UNIT_OF_MEASURE_ID
UNIT_OF_MEASURE
UNIT_OF_MEASURE_ID
UNIT_OF_MEASURE
I should be able to insert the PO master along with as many PO detail records in one shot while pressing a SAVE BUTTON. Unit of measure in the detail section should be a drop down list (filled from the UNIT_OF_MEASURE table)
Kindly suggest how to achieve this easily. Thanks in advance!

This depends on your models being set up correctly:
class PurchaseOrder extends \Eloquent
{
protected $fillable = [
'subject',
'date'
];
public function detail()
{
return $this->hasMany('PurchaseOrderDetail');
}
}
class PurchaseOrderDetail extends \Eloquent
{
protected $fillable = [
'description',
'amount',
'qty'
];
protected $with = [
'unitOfMeasure',
];
public function header()
{
return $this->belongsTo('PurchaseOrder');
}
public function unitOfMeasure()
{
return $this->hasOne('UnitOfMeasure');
}
}
class UnitOfMeasure extends \Eloquent
{
protected $fillable = [
'name'
];
public function lineItems()
{
return $this->belongsToMany('PurchaseOrderDetail');
}
}
You also need to set up your migrations using the proper settings, like so:
//migration for purchaseorder table
public function up()
{
Schema::create('purchaseorders', function(Blueprint $table)
{
$table->increments('id');
$table->string('subject');
$table->string('date');
$table->timestamps();
});
}
//migration for purchaseorderdetail table
public function up()
{
Schema::create('purchaseorderdetails', function(Blueprint $table)
{
$table->increments('id');
$table->integer('purchaseorder_id')->unsigned()->index();
$table->integer('unitofmeasure_id')->unsigned()->index();
$table->foreign('purchaseorder_id')->references('id')->on('purchaseorders');
$table->string('description');
$table->float('amount');
$table->float('qty');
$table->timestamps();
});
}
//migration for unitsofmeasure table
public function up()
{
Schema::create('unitsofmeasure', function(Blueprint $table)
{
$table->increments('id');
$table->string('name');
$table->timestamps();
});
}
That should get you fairly close to what you need, I hope. :) You can then query for your items like so:
$po-details = PurchaseOrderDetail::with(['purchaseOrder', 'unitOfMeasure')->find($id);
This is what an overly simplified controller method may look like:
class PurchaseOrderController
{
public function show($id)
{
$purchaseOrders = PurchaseOrder::with('detail')->find($id);
return View::make('purchaseOrder.show', compact('purchaseOrders'));
}
}
And then your view:
#foreach ($purchaseOrders as $purchaseOrder)
#foreach ($purachseOrder->detail as $lineItem)
#endforeach
#endforeach

Related

Laravel 7 One To Many Relations?

Below are all of the models, migrations and controller.
Donation Model
class Donation extends Model
{
protected $guarded =[];
public function users(){
return $this->hasMany(User::class);
}
public function items(){
return $this->belongsTo(DonationItems::class);
}
}
Donation Items Model:
class DonationItems extends Model
{
protected $guarded=[];
public function donation(){
return $this->hasMany(Donaition::class);
}
}
Donation Items Migration:
public function up()
{
Schema::create('donation_items', function (Blueprint $table) {
$table->id();
$table->string('category');
$table->timestamps();
});
}
Donation Migration:
public function up()
{
Schema::create('donations', function (Blueprint $table) {
$table->id();
$table->string('item');
$table->unsignedInteger('user_id');
$table->unsignedInteger('donation_item_id');
$table->timestamps();
});
}
In my controller I want to access the items as follows:
$don = Donation::all();
$don->items;
But I'm unable to achieve this.
Its not working because laravel follows one rule for relationships:
Remember, Eloquent will automatically determine the proper foreign key column on the Comment model. By convention, Eloquent will take the "snake case" name of the owning model and suffix it with _id. So, for this example, Eloquent will assume the foreign key on the Comment model is post_id.
So you can try by supplying local and foreign id
So it would look something like this
Donation Model
class Donation extends Model
{
protected $guarded =[];
public function users(){
return $this->hasMany(User::class);
}
public function items(){
return $this->belongsTo(DonationItems::class, 'donation_item_id', 'id');
}
}
Donation Items Model:
class DonationItems extends Model
{
protected $guarded=[];
public function donation(){
return $this->hasMany(DonationItems::class, 'id', 'donation_item_id');
}
}
I am writing from my head you might need to swap local and foreign ID's

Get data from tables with one to one relation for API in Laravel

I'm working on my first Laravel project, and I want to create a REST Api for android application. In my system, I have two tables: categories and images. Table images has column category_id which is a foreign key that references column id on category table.
The categories table
//users table migration
class CreateCategoriessTable extends Migration
{
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
}
...
}
The images table
class CreateImagesTable extends Migration
{
public function up()
{
Schema::create('images', function(Blueprint $table){
$table->increments('id');
$table->string('name')
$table->integer('category_id')->unsigned();
$table->foreign('category_id')
->references('id')
->on('categories')
->onDelete('cascade');
$table->timestamps();
});
}
...
}
In the Images model class I did it:
class Images extends Model
{
protected $fillable = ['name'];
protected $hidden = array('created_at', 'updated_at');
public function category(){
$this->belongsTo('App\Category');
}
}
I also created CategoryResource() class as:
class CategoryResource extends JsonResource
{
public function toArray($request)
{
return [
'id'=> $this->id,
'name' => $this->name,
];
}
}
So, I created a CategoryController to with the API methods, and configured the routes to access the corresponding function. The api/category/ url via GET is redirect to the index function of my controller, and the function is like that:
public function index()
{
$categories = Category::get();
return CategoryResource::collection($categories);
}
With this, I can get the categories table data, but I would like merge the users and images table, and get something like this as response:
[
{
'id': 1,
'name': 'category_name',
'image': 'image_name'
}
]
How I can do this?
First add a hasOne relation in Category model for image like this
Category Model
public function image(){
return $this->hasOne('App\Image');
}
Now specify the relation in your CategoryResource
class CategoryResource extends JsonResource
{
public function toArray($request)
{
return [
'id'=> $this->id,
'name' => $this->name,
'image' => new ImageResource($this->whenLoaded('image'))
];
}
}
Create ImageResource for loading images
class ImageResource extends JsonResource
{
public function toArray($request)
{
return [
'id'=> $this->id,
'name' => $this->image_name,
];
}
}
Finally load images relations with eager load in your controller like this
public function index()
{
$categories = Category::with('image')->get();
return CategoryResource::collection($categories);
}

Laravel display data from one database table by using the id of that row

So I have a table pages, that looks like this:
public function up()
{
Schema::create('pages', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->string('name');
$table->integer('category')->unsigned();
] });
Schema::table('pages', function($table) {
$table->foreign('user_id')->references('id')->on('core_users')
->onUpdate('cascade')->onDelete('cascade');
$table->foreign('category')->references('id')->on('ecommerce_payment_pages_categories')
->onUpdate('cascade')->onDelete('set null');
});
}
public function down()
{
Schema::drop('pages');
}
And a table categories looking like this:
public function up()
{
Schema::create('ecommerce_payment_pages_categories', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('core_users')
->onUpdate('cascade')->onDelete('cascade');
$table->string('name');
$table->timestamps();
});
}
public function down()
{
Schema::drop('categories');
}
The pages model looks like this:
class Pages extends Model
{
protected $table = 'pages';
public function user() {
return $this->belongsTo("\App\User");
}
protected $fillable = [
];
protected $casts = [
];
public function categories() {
return $this->belongsTo("\App\Models\Categories");
}
}
And the categories model looks like this:
class PaymentPagesCategories extends Model
{
protected $table = 'categories';
public function user() {
return $this->belongsTo("\App\User");
}
protected $fillable = [
];
protected $casts = [
];
public function pages_categories() {
return $this->hasMany("\App\Models\\Pages");
}
}
So in my pages table I save in the column category the id of the category that the user selects from a dynamic select that echoes the category id as value and category names as options. But I cannot save it as simple string because in another menu the user has the option to delete categories, so I want that when a category gets deleted to get deleted from the category column in the page table as well. Right now I display the data from the database like this:
public function getGet()
{
return response()->json(['success' => true, 'payment_pages' => \Auth::user()->payment_pages()->orderBy('id', 'ASC')->get()]);
}
So for the currently authenticated user I display all the data from the page database table.
Right now after the user selects a category from my select I save on the category colum in pages table the ID of the category. I need to make a query in order to display in a different view in html the corresponding to the category id I saved in pages table
Category column in page migration is not set to allow null values.
To allow null values append nullable column modifier to category column.
Rest of the code seems OK.
Page Migration:
public function up()
{
Schema::create('pages', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->string('name');
$table->integer('category')->unsigned()->nullable(); // <= add this modifier
});
Schema::table('pages', function($table) {
$table->foreign('user_id')->references('id')->on('core_users')
->onUpdate('cascade')->onDelete('cascade');
$table->foreign('category')->references('id')->on('ecommerce_payment_pages_categories')
->onUpdate('cascade')->onDelete('set null');
});
}

laravel eloquent relationship hierarchy

I seem to be having a problem understanding this hierarchical relationship.
Farm > Fields > Shepherds > Sheep
It seems a pretty straightforward hierarchy - Farm hasMany fields, field hasMany shepherds, shepherd hasMany sheep.
Sheep belong to a shepherd, shepherds belongs to fields, fields belong to farms.
I have defined this model relationships thus:
class Sheep extends Model {
protected $fillable ['name'];
public function shepherd() {
return $this->belongsTo('App\Shepherd');
}
}
class Shepherd extends Model {
protected $fillable ['name'];
public function field() {
return $this->belongsTo('App\Field');
}
public function sheep() {
return $this->hasMany('App\Sheep');
}
}
class Field extends Model {
protected $fillable ['name'];
public function farm() {
return $this->belongsTo('App\Farm');
}
public function shepherd() {
return $this->hasMany('App\Shepperd');
}
}
class Farm extends Model {
protected $fillable ['name'];
public function field() {
return $this->hasMany('App\Field');
}
}
public function up()
{
Schema::create('farms', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
});
}
public function up()
{
Schema::create('fields', function (Blueprint $table) {
$table->increments('id');
$table->integer('farm_id');
$table->string('name');
});
}
public function up()
Schema::create('shepherds', function (Blueprint $table) {
$table->increments('id');
$table->integer('field_id');
$table->string('name');
});
}
public function up()
Schema::create('sheep', function (Blueprint $table) {
$table->increments('id');
$table->integer('shepherd_id');
$table->string('name');
});
}
I would expect to be able to save each model in the following manner.
$farm = new App\Farm;
$farm->name = 'West Farm';
$field = new App\Field;
$field->name = 'The orchard';
$shepherd = new App\Shepherd;
$shepherd->name = 'Jason';
$sheep = new App\Sheep;
$sheep->name = 'Sean';
$farm->save();
$farm->field()->save($farm);
$farm->field->shepherd()->save($shepherd);
$farm->field->shepherd->sheep()->save($sheep);
But it does not work. Once I get to $farm->field->shepherd()->save($shepherd); the process breaks down. I would appreciate some assistance in the correct manner of saving using the relationships between all the tables.
I'm pulling my hair out trying to understand this, so any help would be greatly appreciated.
thanks
Your code breaks here:
$farm->field->shepherd()->save($shepherd);
Farms have many fields, so when you reference $farm->field, you're getting a collection of Field object, not just a single Field object.
To make it work, you need to either reference $farm->field[0]
$farm->field[0]->shepherd()->save($shepherd);
or just use the $field object you created before:
$field->shepherd()->save($shepherd);
I'd also suggest to use plural names for your hasMany relations (fields, sheeps, etc.) - this way you'll always remember that the referenced fields refer to a collection, not a single object

Laravel 4 relation not working

I have the follow migration code (simplified):
Ads Table
class CreateAdsTable extends Migration {
public function up()
{
Schema::create('ads', function(Blueprint $table) {
$table->increments('id');
$table->integer('authors_id')->unsigned()->index();
$table->foreign('authors_id')->references('id')->on('authors');
$table->timestamps();
});
}
}
Authors Table
class CreateAuthorsTable extends Migration {
public function up()
{
Schema::create('authors', function(Blueprint $table) {
$table->increments('id');
$table->string('name', 200);
$table->timestamps();
});
}
}
And my models are:
Ad Model
class Ad extends \Eloquent {
protected $table = 'ads';
// Ad __hasOne__ Author
public function author() {
$this->belongsTo('Author');
}
}
Author Model
class Author extends \Eloquent {
// The database table used by the model
protected $table = 'authors';
// Author __hasMany__ Ads
public function ads() {
$this->hasMany('Ad');
}
}
But when I try to get the author using Ad::find(1)->author i receive Relationship method must return an object of type Illuminate\Database\Eloquent\Relations\Relation.
Someone can help me and find the error?
You have to return it:
return $this->belongsTo('Author');

Categories