My relations:
Content mode =>
class Content extends Model
{
use HasFactory;
protected $table = "contents";
protected $fillable = [ "body", "camapaign_id" ];
public function campaigns(){
return $this->belongsTo(Campaign::class, "campaign_id");
}
}
My camapaign model =>
class Campaign extends Model
{
use HasFactory;
protected $table = "campaigns";
protected $fillable = [ "ringba_campaign_id", "is_active" ];
public function contents(){
return $this->hasMany(Content::class, "content_id");
}
}
Here are my migrations:
content table =>
public function up()
{
Schema::create('contents', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->string("body", 255);
$table->foreignIdFor(\App\Models\Campaign::class)->nullable();
});
}
Campaign table =>
public function up()
{
Schema::create('campaigns', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->string("ringba_campaign_id", 255);
$table->boolean("is_active")->default(0);
});
}
Here is my content controller:
public function index(){
$contents = Content::all()->sortBy("created_at");
return view("Dashboard.Contents.contents", [
"contents" => $contents
]);
}
I am trying to access ringba_camapaign_id in here like this =>
#foreach($contents as $content)
{{ $content->campaign_id->ringba_campaign_id }}
#endforeach
But I am getting this error : Attempt to read property on int
A couple of things here, since Content BelongsTo a Campaign the method should be singular.
public function campaign(): BelongsTo
{
return $this->belongsTo(Campaign::class, 'campaign_id');
}
Then when you do $content->campaign_id you are getting the property on the model and so is returning an int. What you want to do is return the campaign model like so $content->campaign through the relationship defined in the Content model. Now you can access the property on the campaign model, $content->campaign->ringba_campaign_id.
However it also looks like a campaign can be nullable by your migration so you would need to add protection from this so you don't get property on null errors. So this would look like optional($content->campaign)->ringba_campaign_id, this would then return null if the Content didn't have a Campaign.
Actually I wrote bad relation code inside content model:
Before I wrote:
public function campaigns(){
return $this->belongsTo(Campaign::class);
}
Answer will be :
public function campaign(){
return $this->belongsTo(Campaign::class);
}
I wrote campaigns instead of campaign.
try this.
#foreach($contents as $content)
{{ $content->campaigns->ringba_campaign_id }}
#endforeach
for more information check this link
Related
I have two tables Department and InspectionSite.
Department Migration
public function up()
{
Schema::create('departments', function (Blueprint $table) {
$table->id();
$table->string('department_name', 100);
});
}
InspectionSite Migration:
public function up()
{
Schema::create('inspection_sites', function (Blueprint $table) {
$table->id();
$table->string('site_title');
$table->foreignIdFor(\App\Models\Department::class);
$table->timestamps();
});
}
Department Model:
class Department extends Model
{
use HasFactory;
protected $fillable = ['depatment_name'];
public function sites() {
return $this->hasMany(InspectionSite::class);
}
}
InspectionSite Model
class InspectionSite extends Model
{
use HasFactory;
protected $guarded = [];
public function department() {
return $this->belongsTo(Department::class, 'department_id');
}
}
getting data from controller
public function get() {
$selector = ['site_title AS title', 'site_type' ];
$sites = InspectionSite::all();
return response()->json($sites->department, 200);
}
when I call find() method it returns relationship data but not in all() method?
public function get() {
$departments = Department::all();
return response()->json($departments->sites, 200);
}
Error details
all() method returns Collection of models and each model should have department relation.
When you are trying to return this:
return response()->json($sites->department, 200);
You are accessing department property on Collection instance.
Instead you should call it on each model of that collection.
Here you can try solutions, depending what you want to achieve
Solution 1: (recomended)
$sites = InspectionSite::with('department')->get();
return response()->json($sites, 200);
// result
[
{
...
department: ...
}
...
]
Solution 2: (Returns only depertments, not InspectionSite properties)
$sites = InspectionSite::with('department')->get()
->map(function($s) {
return $s->department;
});
return response()->json($sites, 200);
// result
[
{
[department]
}
{
[department]
}
]
Migration persons Table:
Schema::create('persons', function (Blueprint $table) {
$table->id();
$table->string("firstname");
$table->string("lastname");
$table->timestamps();
});
Migration passports Table:
Schema::create('passports', function (Blueprint $table) {
$table->id();
$table->string("identifystring")->unique();
$table->unsignedBigInteger("person_id");
$table->timestamps();
$table->foreign("person_id")->references("id")->on("persons")->onDelete("cascade");
});
Person model:
class Person extends Model
{
use HasFactory;
protected $table ="persons";
protected $fillable = [
"firstname",
"lastname"
];
public function passport() {
$this->hasOne(\App\Models\Passport::class, "passports.person_id","persons.id");
}
}
Passport Model:
class Passport extends Model
{
use HasFactory;
protected $table = "passports";
protected $fillable = [
"identifystring",
"person_id"
];
}
execute Code:
$person = \App\Models\Person::findOrFail(2);
dd($person->passport());
Result is: null
class Person extends Model
{
use HasFactory;
protected $table ="persons";
protected $fillable = [
"firstname",
"lastname"
];
public function passport() {
$this->hasOne(\App\Models\Passport::class, "person_id", "id");
}
}
You did not return the relation. just return it:
public function passport() {
return $this->hasOne(\App\Models\Passport::class, "passports.person_id","persons.id");
}
As per the migrations written. In the Person model write
public function passport() {
return $this->hasOne(\App\Models\Passport::class, "person_id","id");
}
and in the Passport model write
public function person() {
return $this->belongsTo(\App\Models\Person::class, 'id', 'person_id');
}
Execute the code
$person = \App\Models\Person::findOrFail(2)->passport;
dd($person);
Use this code.
In your Person Model
public function passport() {
return $this->hasOne(\App\Models\Passport::class);
}
In your passport model
public function person() {
return $this->belongsTo(\App\Models\Person::class, 'person_id');
}
Then try to pass the relation again by doing the same thing
$person = \App\Models\Person::findOrFail(2);
dd($person->passport());
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);
}
It's a table migrated from https://github.com/lucadegasperi/oauth2-server-laravel
In the table oauth_clients, the field data type of id is varchar(40), not int.
$name = Input::get('name');
$id = str_random(40);
$secret = str_random(40);
$client = new oauthClient;
$client->name = $name;
$client->id = $id;
$client->secret = $secret;
$client->save();
After save(); the $client->id become '0', not the string I assigned.
That makes the following relation table save fail.
$endpoint = new OauthClientEndpoint(array('redirect_uri' => Input::get('redirect_uri));
$client->OauthClientEndpoint()->save($endpoint);
I checked the $client->id: after save, it becomes 0 and I get an error including this one:
(SQL: insert into `oauth_client_endpoints` (`redirect_uri`, `client_id`, `updated_at`, `created_at`) values (http://www.xxxxx.com, 0, 2014-09-01 11:10:16, 2014-09-01 11:10:16))
I manually saved an endpoint to prevent this error for now. But how do I resolve this issue?
Here's my model:
class OauthClient extends Eloquent {
protected $table = 'oauth_clients';
public function OauthClientEndpoint(){
return $this->hasOne('OauthClientEndpoint', 'client_id', 'id');
}
}
class OauthClientEndpoint extends Eloquent {
protected $table = 'oauth_client_endpoints';
protected $fillable = array('redirect_uri');
public function OauthClient(){
return $this->belongsTo('OauthClient', 'client_id', 'id');
}
}
class CreateOauthClientsTable extends Migration {
public function up() {
Schema::create('oauth_clients', function (Blueprint $table) {
$table->string('id', 40);
$table->string('secret', 40);
$table->string('name');
$table->timestamps();
$table->unique('id');
$table->unique(array('id', 'secret'));
});
}
public function down() {
Schema::drop('oauth_clients');
}
}
class CreateOauthClientEndpointsTable extends Migration {
public function up() {
Schema::create('oauth_client_endpoints', function (Blueprint $table) {
$table->increments('id');
$table->string('client_id', 40);
$table->string('redirect_uri');
$table->timestamps();
$table->foreign('client_id')
->references('id')->on('oauth_clients')
->onDelete('cascade')
->onUpdate('cascade');
});
}
public function down() {
Schema::table('oauth_client_endpoints', function ($table) {
$table->dropForeign('oauth_client_endpoints_client_id_foreign');
});
Schema::drop('oauth_client_endpoints');
}
}
When you are setting your own ID and not using auto_increment be sure to add public $incrementing = false; to that model. In your case you want:
class OauthClient extends Eloquent {
public $incrementing = false;
protected $table = 'oauth_clients';
public function OauthClientEndpoint(){
return $this->hasOne('OauthClientEndpoint', 'client_id', 'id');
}
}
This is a tiny red block in the huge Laravel documentation:
Note: Typically, your Eloquent models will have auto-incrementing keys. However, if you wish to specify your own keys, set the incrementing property on your model to false.
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