laravel eloquent one-to-one save relation - php

Having first steps in laravel, and just hit the wall.
I Have two entities:
Schema::create('company', function (Blueprint $table) {
$table->engine = "InnoDB";
$table->increments('id');
$table->string('name')->unique();
$table->integer('addressid')->unsigned()->nullable();
});
and
Schema::create('addresses', function (Blueprint $table) {
$table->engine = "InnoDB";
$table->increments('id');
$table->string('street');
(...)
});
Schema::table('company', function($table) {
$table->foreign('addressid')
->references('id')->on('addresses')
->onDelete('cascade');
});
Models are
class Address extends Model {
public function shipyard() {
return $this->belongsTo('App\Company', 'addressid');
}
}
class Company extends Model {
public function address() {
return $this->hasOne('App\Address', 'id', 'addressid');
}
}
When I want to create these entities in DB I use one form in HTML to gather all data. Then I post request and do:
Route::post('/company', function (Request $request) {
(...validation...)
$company = new Company();
$company->name = $request->name;
$address = new Address();
$address->street = $request->street;
(...)
$company->address()->save($address);
$company->save();
return redirect('/');
});
As a result I have two entities in DB, but the "addressid" field is null. Why?

Change relation in company (relation in address you can delete):
class Company extends Model {
public function address() {
return $this->belongsTo('App\Address', 'addressid');
} }
Saving code:
Route::post('/company', function (Request $request) {
(...validation...)
$company = new Company();
$company->name = $request->name;
$address = new Address();
$address->street = $request->street;
(...)
$address->save();
$company->address()->associate($address);
$company->save();
return redirect('/');
});

class Address extends Model {
// Added fillable array for mass assigment
protected $fillable = ['street'];
public function shipyard() {
return $this->belongsTo('App\Company', 'addressid');
}
}
class Company extends Model {
// Added fillable for mass assignment
protected $fillable = ['name','addressid'];
// The second argument for the hasOne takes a foreign key not a primary key
public function address() {
return $this->hasOne('App\Address', 'addressid');
}
}
$company = new Company();
$company->name = $request->name;
$company->save();
$company->address()->create($request->street)

Related

laravel 9.0 Eloquent all() method doesn't return relationship

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]
}
]

Laravel PHP: how to join each element of collection after update?

I have Clients collection in Laravel. $clients = Client::all();
I need to update it with a user's name for each item inside a collection.
This is my code:
$clients = Client::all();
$clients->each(function ($item, $key) {
if ($item->user()->first())
{
$user = $item->user()->first();
$name = $user->name;
} else $name = '';
$client = collect($item);
$client = $client->union(['user' => $name]);
});
The question is what is a proper way to form $clients Collection with $client updated.
So I need to return $clients whith user name included.
Models:
// Client Model
public function user()
{
return $this->belongsTo('App\User');
}
// User Model
public function clients()
{
return $this->hasMany('App\Client');
}
Migration:
Schema::create('clients', function (Blueprint $table) {
$table->bigIncrements('id');
$table->char('name', 200)->nullable();
$table->char('city', 100)->nullable();
$table->char('type', 20)->nullable();
$table->foreign('user_id')->references('id')->on('users');
$table->unsignedBigInteger('user_id')->nullable();
$table->timestamps();
$table->softDeletes();
You can do something like below:
$clients = Client::all();
$clients->each(function ($item, $key) {
$name = $item->user ? $item->user->name : "";
return $name; // will append name in this client collection
});
return $clients
To read more about each method visit
Hope it helps.
Thanks

ERROR SQLSTATE[HY000]: General error: 1364 Field 'name' doesn't have a default value (SQL: insert into `favorites` () values ())

I am trying to copy a station from the station repository and add it to my favorite repository. I am in a laravel rest API. Thanks for the help!
Here is my controller:
class FavoriteController extends Controller
{
private $favoriteRepository;
private $stationRepository;
public function __construct(FavoriteRepository $favoriteRepository, StationRepository $stationRepository)
{
$this->favoriteRepository = $favoriteRepository;
$this->stationRepository = $stationRepository;
}
public function store(int $station_id)
{
$favorite = array();
$favorite[] = $this->stationRepository->findByField("id", $station_id);
$this->favoriteRepository->create($favorite);
return response()->json($favorite, 201);
}
}
Here is the database for the favorites:
public function up()
{
Schema::create('favorites', function (Blueprint $table) {
$table->string('name');
$table->string('city');
$table->foreign('city')->references('name')->on('cities');
$table->integer('station_id')->unsigned();
$table->foreign('station_id')->references('id')->on('stations')->onDelete('cascade');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
#$table->boolean('is_private');
});
}
Here is my Favorite model
class Favorite extends Model
{
protected $fillable = ['station_id', 'user_id', 'updated_at', 'name', 'city'];
public $timestamps = false;
}
And I have both these methods in my repos:
function model()
{
return "App\\Station";
}
Try this
public function store($station_id)
{
$favorite = $this->stationRepository->where("id", $station_id)->first()->toArray();
$this->favoriteRepository->create($favorite);
return response()->json($favorite, 201);
}
}

Laravel 5.1 Foreign Key Trouble

I have some trouble getting the foreign key.
My Migrations looks like this (shortened them):
<?php
class CreateProductsTable extends Migration
{
public function up()
{
Schema::create('products', function (Blueprint $table) {
$table->increments('id');
$table->string('email');
$table->string('title');
$table->string('filename');
$table->integer('number_of_chapters');
$table->text('input_mpg');
$table->timestamps();
});
}
public function down()
{
Schema::drop('products');
}
}
<?php
class CreateChaptersTable extends Migration
{
public function up()
{
Schema::create('chapters', function (Blueprint $table) {
$table->increments('id');
$table->integer('product_id')->unsigned();
$table->time('input-chapter-start1');
$table->time('input-chapter-end1');
$table->timestamps();
});
Schema::table('chapters', function($table) {
$table->foreign('product_id')->references('id')->on('products');
});
}
public function down()
{
Schema::drop('chapters');
}
}
And my 2 Model like this:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Chapters extends Model
{
protected $table = 'chapters';
protected $fillable = ['input-chapter-start1', 'input-chapter-end1'];
public function product()
{
return $this->belongsTo('App\Product');
}
}
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
protected $table = 'products';
protected $fillable = ['email', 'title', 'filename', 'inputMpg', 'number_of_chapters'];
public static $rules = [
'email' => 'required|email|max:50',
'title' => 'required|max:50',
'filename' => 'required|max:50',
'input_mpg' => 'required'
];
public function Chapters()
{
return $this->hasMany('App\Chapters');
}
}
And just save it like this in my Controller
$product->save();
$Chapters->save();
And get following error:
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or
update a child row: a foreign key constraint fails
(generator.chapters, CONSTRAINT chapters_product_id_foreign
FOREIGN KEY (product_id) REFERENCES products (id)) (SQL: insert
into chapters (input-chapter-start1, input-chapter-end1,
updated_at, created_at) values (12:12:12, 12:12:12, 2016-04-25
11:41:31, 2016-04-25 11:41:31))
EDIT
Controller looks like this:
namespace App\Http\Controllers;
class ProductController extends Controller
{
protected $request;
public function request(Request $request)
{
$this->request = $request;
}
public function createProduct(Request $request)
{
$product = new Product;
$Chapters = new Chapters($request->all());
$data = $request->all();
$projectEmail = $request->input('email');
$projectTitle = $request->input('title');
$projectFile = $request->input('filename');
$projectChapters = $request->input('number_of_chapters');
$validator = Validator::make($request->all(), Product::$rules);
if($validator->fails())
{
return Redirect::back()->withInput()->withErrors($validator);
}
$product->fill($data);
if($product->save())
{
$Chapters->product()->associate($product);
$Chapters->save();
return redirect()->route('root')->with('message', 'success')->withInput();
}
else
{
return redirect()->route('newProduct')->with('message', 'Error')->withInput();
}
}
}
Edit I tried Samsquanch suggestion:
And added this in my controller:
$product->save();
$Chapters->product()->associate($product);
$Chapters->save();
but still get this error message:
BadMethodCallException in Builder.php line 2093: Call to undefined
method Illuminate\Database\Query\Builder::products()
The problem is that you're not telling Laravel or MySQL what the foreign key should be.
You have two options here (both from the documentation: https://laravel.com/docs/5.1/eloquent-relationships#inserting-related-models)
The first option would be to save chapters through product:
$chapters = $product->chapters()->saveMany($Chapters); // or just->save() if it's only one
The second (and how I generally do it) would be to use associate() which relies on the belongsTo relationship in your Chapters model:
$product->save();
$Chapters->product()->associate($product);
$Chapters->save();
There's also a third, but not recommended, option of just setting the foreign key yourself manually.
Edit:
$product->chapters()->associate($Chapters);
$product->save();

Laravel Eloquent after save id becomes 0

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.

Categories