I am trying to store data to the server with laravel. I am following a tutorial and I feel like it may be slightly out of date because I was getting a 500 error earlier with an update method.
public function store()
{
$input = Input::json();
return Player::create(array(
'teamName' => $input->teamName, // this is line 35
'teamColor' => $input->teamColor
));
}
The above is what the tutorial's syntax is like, I tried the below as well.
public function store()
{
$input = Input::all();
return Player::create(array(
'teamName' => $input['teamName'], // this is line 35
'teamColor' => $input['teamColor']
));
}
Inside the browser I get this error.
{"error":{"type":"ErrorException","message":"Undefined property: Symfony\\Component\\HttpFoundation\\ParameterBag::$teamName","file":"C:\\wamp\\www\\basketball-app-framework\\app\\controllers\\PlayersController.php","line":35}}
So I feel like these issues I should be able to figure out in a matter of seconds, but I am new and really don't know where to find a clear answer. I tried searching the docs, but I can't find what I am looking for, maybe I am being blind?
Try to use:
public function store()
{
return Player::create(array(
'teamName' => Input::get('teamName'),
'teamColor' => Input::get('teamColor')
));
}
Getting a mass assignment error, means that you need to edit your model and add the $fillable variable to it:
class Player extends Eloquent {
protected $fillable = array('teamName', 'teamColor');
}
Laravel tries to protect you from mass assignments, so you have to tell it which columns are ok to mass assign.
Request (Input) docs: http://laravel.com/docs/requests.
CheatSheet: http://cheats.jesse-obrien.ca/.
Mass assignment: http://laravel.com/docs/eloquent#mass-assignment.
Related
Is there a way to invoke eloquent relationship methods without changing the original eloquent collection that the method runs on? Currently I have to employ a temporary collection to run the method immutable and to prevent adding entire related record to the response return:
$result = Item::find($id);
$array = array_values($result->toArray());
$temp = Item::find($id);
$title = $temp->article->title;
dd($temp); //This prints entire article record added to the temp collection data.
array_push($array, $title);
return response()->json($array);
You are not dealing with collections here but with models. Item::find($id) will get you an object of class Item (or null if not found).
As far as I know, there is no way to load a relation without storing it in the relation accessor. But you can always unset the accessor again to delete the loaded relation (from memory).
For your example, this process yields:
$result = Item::find($id);
$title = $result->article->title;
unset($result->article);
return response()->json(array_merge($result->toArray(), [$title]));
The above works but is no very nice code. Instead, you could do one of the following three things:
Use attributesToArray() instead of toArray() (which merges attributes and relations):
$result = Item::find($id);
return response()->json(array_merge($result->attributesToArray(), [$result->article->title]));
Add your own getter method on the Item class that will return all the data you want. Then use it in the controller:
class Item
{
public function getMyData(): array
{
return array_merge($this->attributesToArray(), [$this->article->title]);
}
}
Controller:
$result = Item::find($id);
return response()->json($result->getMyData());
Create your own response resource:
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class ItemResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'title' => $this->article->title,
'author' => $this->article->author,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
}
Which can then be used like this:
return new ItemResource(Item::find($id));
The cleanest approach is option 3. Of course you could also use $this->attributesToArray() instead of enumerating the fields, but enumerating them will yield you security in future considering you might extend the model and do not want to expose the new fields.
I see two ways you can achieve that.
First, you can use an eloquent Resource. Basically it'll allow you to return exactly what you want from the model, so in your case, you'll be able to exclude the article. You can find the documentation here.
The second way is pretty new and is still undocumented (as fas i know), but it actually works well. You can use the unsetRelation method. So in your case, you just have to do:
$article = $result->article; // The article is loaded
$result->unsetRelation('article'); // It is unloaded and will not appear in the response
You can find the unsetRelation documentation here
There is not as far as I know. When dealing with Model outputs, I usually construct them manually like this:
$item = Item::find($id);
$result = $item->only('id', 'name', 'description', ...);
$result['title'] = $item->article->title;
return $result;
Should you need more power or a reusable solution, Resources are your best bet.
https://laravel.com/docs/5.6/eloquent-resources#concept-overview
I am having this error and none of the googled result i checked is similar to my problem.
I have an application with class Deal, User, and Matches
A deal has many matches.
A user has many matches.
A user has many deals.
I am attempting to create a new Match using my Deal object
$deal->matches()->create(['user_id'=>$id]);
This is my match class, i have defined all needed relationships
class Match extends Model
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $guarded = [];
public $timestamps = false;
public $expired_on = "";
public static function boot()
{
parent::boot();
static::creating(function ($model) {
$model->matched_on = $model->freshTimestamp();
});
}
public function __construct(){
$d = (new \DateTime($this->matched_on))->modify('+1 day');
$this->expired_on = $d->format('Y-m-d H:i:s');
}
/**
* Get the user that owns the match.
*/
public function user()
{
return $this->belongsTo('App\User');
}
/**
* Get the deal that owns the match.
*/
public function deal()
{
return $this->belongsTo('App\Deal');
}
}
And i keep getting this error when i attempt to create a new match.
QueryException in Connection.php line 647:
SQLSTATE[HY000]: General error: 1364 Field 'user_id' doesn't have a default value (SQL: insert into matches (deal_id) values (1))
I have my guarded to be an empty array, what could be the problem?
Remove the guarded array and add the fillable instead:
protected $fillable = ['user_id', 'deal_id'];
If you would like to revert to previous behavior, update your
config/database.php
file and set 'strict' => false for your connection.
Since it was a unique field in my case, I could not make it nullable.
For me, I had an empty constructor which was causing the issue don't know why.
Please comment if anyone knows the reason.
public function __construct(){
}
Commenting/removing it resolved the issue.
If you have a constructor in your model, just make sure it has a call to a parent constructor as well:
public function __construct( array $attributes = array() ) {
// mandatory
parent::__construct($attributes);
//..
}
Otherwise, it will break some functionality like Model::create.
Alexey Mezenin's Answer is correct and a good one.
Another way i used around it, for those who want to maintain the guarded empty array is to create a new Match object and put in the attributes and save.
$match->user_id = $id;
$match->deal_id = $deal->id;
$match->matched_on = $match->freshTimestamp();
$match->save();
I am using Laravel 8 and fixed this error thorugh this two steps:
move the word from $guarded array to $fillable array in User Mode
Config.database.php: 'strict' => false in the array of 'mysql'
Another way around this error is to include
'strict' => false,
into config/database.php within mysql array
When manually importing / exporting the databases, check if the transfer of all table settings was successful. If you forget to add an auto increment primary key, Laravel doesn't fill the value for you.
Adding the AUTO_INCREMENT afterwards will solve the problem.
I had this error but my wrong was making class model:
$book = new Book();
While this is true
$book = new Book($request->all());
changing your "config/database.php" won't help.
If you're getting this error, you're not sending the data to database correctly.
check your function in your controller, the create() method is probably being blocked by an if statement or something.
or
if it's an API, check the post request from the frontend that's where your issue is.
make sure the form is correctly passed into to request.
When I try to fill my database using the model method create like this:
public function registerDevice($command) {
$deviceId = $command->deviceId;
$deviceToken = $command->deviceToken;
$this->deviceId = $deviceId;
$this->deviceToken = $deviceToken;
Device::create(array('device_id' => $deviceId, 'device_token' => $deviceToken));
$this->raise(new DeviceWasRegistered($this));
return $this;
}
The entry is being made, but only the timestamps are being updates. The value fields are empty. No error coming up or something else is failing. But the values I want to put into the db are there if I var_dump the variables.
Do I miss something out?
In order for the create method to work, you need to put your two fields in the $fillable array on the model. So make sure you have this in your model:
protected $fillable = [
'device_id',
'device_token',
];
You can read more about the create method and mass assignment at http://laravel.com/docs/5.1/eloquent#mass-assignment.
I'm working on a Laravel 5 app using the jenssegers\laravel-mongodb package and I'm trying to get up and running with Factory Muffin to help with rapidly testing and seeding etc.
I have defined relationships in my factory definitions (code below) - and they work when I run seeds to create new records in the database. By "work", I mean they attach related data correctly to the parent model and persist all those records to the database. But they do not work when I run the $muffin->instance('My\Object') method, which creates a new instance without persisting it. All the relations come back as null.
In a way this makes sense. When the models are stored in the database, they are related by the object _id key. That key doesn't exist until the model is stored. So when I call the instance method, I actually can see via debugging that it does generate the models that would be related, but it does not yet have any key to establish the relation, so that data just kinda goes poof.
This is a bummer because I'd like to be able to generate a fully fleshed-out model with its relations and see for example whether it is saved or passes validation and whatnot when I submit its data to my routes and things. I.e., right now I would not be able to check that the contact's email was valid, etc.
Simplified code samples are below - am I going about this in an entirely wrong way? This is my first time working with Mongo and Factory Muffin. Should this even be able to work the way I want it to?
// factories/all.php
$fm->define('My\Models\Event', [
'title' => Faker::text(75),
'contact' => 'factory|My\Models\Contact'
]);
$fm->define('My\Models\Contact', [
'first_name' => Faker::firstName(),
'email' => Faker::email(),
... etc
]);
// EventControllerTest.php
...
/**
* #var League\FactoryMuffin\FactoryMuffin
*/
protected $muffin;
public function setUp()
{
parent::setUp();
$this->muffin = new FactoryMuffin();
$this->muffin->loadFactories(base_path('tests/factories'));
}
...
public function testCanStoreEvent()
{
$event = $this->muffin->instance('Quirks\Models\Event');
echo $event->contact; // returns null
$event_data = $event->toArray();
$this->call('POST', 'events', $event_data);
$retrieved_event = Event::where('title', '=', $event->title)->get()->first();
$this->assertNotNull($retrieved_event); // passes
$this->assertRedirectedToRoute('events.edit', $retrieved_event->id); // passes
// So, the event is persisted and the controller redirects etc
// BUT, related data is not persisted
}
Ok, in order to get factory muffin to properly flesh out mongo embedded relationships, you have to do like this:
// factories/all.php
$embedded_contact = function() {
$definitions = [
'first_name' => Faker::firstName(),
'email' => Faker::email(),
// ... etc
];
return array_map(
function($item) { return $item(); },
$definitions
);
}
$fm->define('My\Models\Event', [
'title' => Faker::text(75),
'contact' => $embedded_contact
]);
If that seems onerous and hacky ... I agree! I'm definitely interested to hear of easier methods for this. For now I'm proceeding as above and it's working for both testing and seeding.
I have a class called Vara, where i have a table field called searchname. I want to do a simple setup of cviebrock eloquent sluggable but can't figure out what the issue is.
When i save my model, nothing happens, it rewrite the old value stored.
If i change in build_from to, whatthefuckisgoingon i get the same output. I have a field called handle, also tried changing the field namne to slug but same result. If i leave build_from empty i also get the same output.
If i however change save_to to something that doesn't exist i get an error. The searchname field does have a value of "Hjordnära test 33 liter", so the output is really wierd.
My guess is that build_from is being ignored, and seen as null. How do i fix this?
My Vara.php looks like this
use Cviebrock\EloquentSluggable\SluggableInterface;
use Cviebrock\EloquentSluggable\SluggableTrait;
class Vara extends \Eloquent implements SluggableInterface {
use SluggableTrait;
protected $sluggable = array(
'build_from' => 'searchname',
'save_to' => 'handle'
);
In my VarorController.php
public function saveVara()
{
$id = Input::get('id');
$vara = Vara::find(Input::get('id'));
$vara->edited_by = Auth::user()->id;
$vara->searchname = Input::get('searchname');
$vara->save();
return $vara->getSlug();
Ok a litle update, found this function in SluggableTrait.php
public function sluggify($force=false)
{
$config = \App::make('config')->get('eloquent-sluggable::config');
$this->sluggable = array_merge( $config, $this->sluggable );
if ($force || $this->needsSlugging())
{
$source = $this->getSlugSource();
$slug = $this->generateSlug($source);
$slug = $this->validateSlug($slug);
$slug = $this->makeSlugUnique($slug);
$this->setSlug($slug);
}
return $this;
}
so if i add $vara->sluggify(true); to my controller the slug is being saved, so now the questions is why it does not sluggify automaticly on $vara->save();
Most probably, it's an issue of validation because you're using Ardent:
Ardent is a package that "provides self-validating smart models for Laravel Framework 4's Eloquent ORM"
Check your rules and use if statement:
if(! $vara->save()) // if model is invalid
dd($vara->errors());
If you don't need to check validation , you may use
$vara->forceSave();
To integrate Eloquent sluggable with Ardent, take a look at this link