The following function in laravel stores my form input. I can't get it to store anything other than the author id and the title. It just won't store the keywords.
Below is the function in my Postcontroller.php
public function store()
{
$input = Input::all();
$rules = array(
'title' => 'required',
'text' => 'required',
);
$validation = Validator::make($input, $rules);
if ($validation->fails()) {
return Redirect::back()->withErrors($validation)->withInput();
} else {
// create new Post instance
$post = Post::create(array(
'title' => $input['title'],
'keywords' => $input['keywords'],
));
// create Text instance w/ text body
$text = Text::create(array('text' => $input['text']));
// save new Text and associate w/ new post
$post->text()->save($text);
if (isset($input['tags'])) {
foreach ($input['tags'] as $tagId) {
$tag = Tag::find($tagId);
$post->tags()->save($tag);
}
}
// associate the post with user
$post->author()->associate(Auth::user())->save();
return Redirect::to('question/'.$post->id);
}
}
Post.php (model)
<?php
class Post extends Eloquent {
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'posts';
/**
* Whitelisted model properties for mass assignment.
*
* #var array
*/
protected $fillable = array('title');
/**
* Defines a one-to-one relationship.
*
* #see http://laravel.com/docs/eloquent#one-to-one
*/
public function text()
{
return $this->hasOne('Text');
}
/**
* Defines an inverse one-to-many relationship.
*
* #see http://laravel.com/docs/eloquent#one-to-many
*/
public function author()
{
return $this->belongsTo('User', 'author_id');
}
/**
* Defines a many-to-many relationship.
*
* #see http://laravel.com/docs/eloquent#many-to-many
*/
public function tags()
{
return $this->belongsToMany('Tag');
}
/**
* Defines an inverse one-to-many relationship.
*
* #see http://laravel.com/docs/eloquent#one-to-many
*/
public function category()
{
return $this->belongsTo('Category');
}
/**
* Defines a polymorphic one-to-one relationship.
*
* #see http://laravel.com/docs/eloquent#polymorphic-relations
*/
public function image()
{
return $this->morphOne('Image', 'imageable');
}
/**
* Defines a one-to-many relationship.
*
* #see http://laravel.com/docs/eloquent#one-to-many
*/
public function comments()
{
return $this->hasMany('Comment');
}
}
You are stopping the mass assignment of keywords with your model settings.
Change
protected $fillable = array('title');
to
protected $fillable = array('title', 'keywords');
Related
I'm following this answer with his pattern:
How to make a REST API first web application in Laravel
At the end my application works with these methods:
LanController
/**
*
* Store the data in database
*
* #param Request $request
* #return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|void
*/
public function store(Request $request)
{
$status = $this->lan_gateway->create($request->all());
/**
* Status is true if insert in database is OK
* or an array of errors
*/
if ($status===true) {
return redirect(route('lan'))
->with('success',trans('common.operation_completed_successfully'));
// validation ok
} else {
return redirect(route('lan-create'))
->withInput()
->withErrors($status);
// validation fails
}
}
LanGateway
/**
* Validate input and create the record into database
*
* #param array $data the values to insert
* #return array $validator errors on fails
* #return bool $status true on success
*/
public function create(array $data)
{
$validator = Validator::make($data, [
'ip_address' => 'required|string'
]);
if ($validator->fails()) {
return $validator->errors()->all();
} else {
$status = $this->lan_interface->createRecord($data);
return $status;
}
}
And this is the interface implemented by repository create method
<?php
/**
* Repository for LAN object.
* PRG paradigma, instead of "User"-like class Model
*
* #see https://stackoverflow.com/questions/23115291/how-to-make-a-rest-api-first-web-application-in-laravel
*/
namespace App\Repositories;
use App\Interfaces\LanInterface;
use Illuminate\Database\Eloquent\Model;
class LanRepository extends Model implements LanInterface
{
/**
* The name of table on database
* #var string The table name on database
*/
protected $table = "lans";
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = ['ip_address'];
public function getAllRecords()
{
$lan = $this->all();
return $lan;
}
/**
*
* Insert record inside database.
*
* #param array $data
* #return bool true on success, false on failure
*/
public function createRecord(array $data)
{
foreach ($data as $key => $value) {
if (in_array($key,$this->fillable)) {
$this->$key = $value;
}
}
$status = $this->save();
return $status;
}
You can see that I "lost" the fillable helper methods, at the end I use only as "needle/haystack".
Is there another implementation possible for my createRecord method to use, as much as possible, Laravel default methods/helpers or am I in the most right direction?
Thank you very much
As you can see in documentation, $fillable property only applies when you are using mass assignment statements.
Now if if (in_array($key,$this->fillable)) { conditional check is just to check if only some allowed set of columns are saved from API, you can create another property lets say protected $allowedToInsert = ['column1', 'column2],..; and then update the conditional :
public function createRecord(array $data)
{
foreach ($data as $key => $value) {
if (in_array($key,$this->allowedToInsert)) {
$this->$key = $value;
}
}
$status = $this->save();
return $status;
}
This way you can use fillable as it is supposed to be used, The approach you have can be the simplest one but you can improve lit of things. See this for your reference
I'm looking for a solution to optimize my Code using Laravel Eloquent.
My issue is that I want to add Attributes conditionally, and this Attributes is basically the a transformed many-to-many relationship.
At the moment I have this in my controller (simplified):
<?php
namespace App\Http\Controller;
/**
* Class Category
*/
class Category extends Controller
{
/**
* #return Collection
*/
public function index()
{
return Category::withCount('countries')->get();
}
/**
* #param int $id
*
* #return Category
*/
public function show($id)
{
$result = Category::where('id', $id)
->with('countries')
->firstOrFail();
$result->countries_list = '';
return $result;
}
}
My Category model looks like this (simplified):
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
/**
* Class Category
*/
class Category extends Model
{
/**
* The accessors to append to the model's array form.
*
* #var array
*/
protected $appends = [
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'countries',
];
/**
* #return string
*/
public function getCountriesCountAttribute()
{
return trans_choice('labels.countries', $this->original['countries_count']);
}
/**
* #return
*/
public function getCountriesListAttribute()
{
return $this->countries->pluck('alpha_2');
}
/**
* Get the related Countries.
*/
public function countries()
{
return $this->belongsToMany(
Country::class,
'category_country',
'category_id',
'country_id'
);
}
}
The Country Model is just a list of Countries with id, name, the Alpha2 Code, etc. I can't use the protected $appends to add countries_list because than the the list would be always included.
I also can't change my Countries model because this is used in several other occurrences.
What I'm looking for is a way to optimize the code in the controller to this:
<?php
namespace App\Http\Controller;
/**
* #return Collection
*/
public function index()
{
return Category::withCount('countries')->get();
}
/**
* #param int $id
*
* #return Category
*/
public function show($id)
{
return Category::where('id', $id)
->withAttribute('countries_list') // An array of all country aplha 2 codes
->firstOrFail();
}
You can access the countries_list attribute after querying (don't include it in your query).
public function show($id)
{
$category = Category::findOrFail($id);
$list = $category->countries_list; // this calls getCountriesListAttribute()
}
I have 2 tables in my application... Users Conventioners
I have users id in the conventioners table and i want to access their genders from the Users table....
I have like 10 user ids in the conventioners table and 20 users in the users table...
Please how do I access all their genders in the users table...
$conventioners->users()->gender
Conventioners is an instance of the Conventioner Model which contains a relationship **belongsToMany
Thanks alot guys
Here is my Conventioner Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Conventioner extends Model
{
/**
* #var string
*/
protected $table = 'conventioners';
/**
* #var array
*/
protected $fillable = [
'user_id','year','church_id','convention_id'
];
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()
{
return $this->belongsTo('App\User');
}
/**
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function users()
{
return $this->hasMany('App\User');
}
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function convention()
{
return $this->belongsTo('App\Convention');
}
}
Here is my ConventionController method called Convention...
It retrieves the details for the current convention
public function convention($slug)
{
if(!$this->admin()) return redirect()->back();
$convention = Convention::where('slug', $slug)->first();
$participants = Conventioner::where('convention_id', $convention->id)->get();
$conventioner = [];
foreach($participants as $participant)
{
$thisUser = [];
$thisUser['data'] = User::withTrashed()->where('id', $participant->user_id)->first();
$thisUser['convention'] = $participant;
array_push($conventioner, $thisUser);
}
var_dump($participants->users()->pluck('gender')->all());
return view('dashboard/conventions/convention', [
'convention' => $convention,
'user' => Auth::user(),
'conventioners' => $convention->conventioners(),
'participants' => $conventioner
]);
}
The problem is that users is a collection not an individual that you can call gender on. If you want a list of all the genders you can use the following:
Conventioner::where('convention_id', $convention->id)->with('users')->get()
$conventioners->pluck('users')->pluck('gender')->all();
This will return an array of the genders. You can read more about pluck here.
The pluck method retrieves all of the values for a given key
i have 3 table/Model such as Users, CurrentCurrency and CurrencyType, in CurrentCurrency 2 column are relation with CurrencyType and Users, as user_id and currency_id
i can use this code to fetch CurrentCurrency user :
$all_records = CurrentCurrency::with('user')->orderBy('id', 'DESC')->paginate(50);
this code return all records with users, now i want to create simple related with CurrencyType by Modeling, unfortunately for this table i get null
CurrentCurrency :
class CurrentCurrency extends Model
{
protected $table = 'current_currency';
protected $fillable = ['currency_id', 'current_money', 'user_id'];
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()
{
return $this->belongsTo('App\User');
}
public function currency_type()
{
return $this->belongsTo('App\CurrencyType');
}
}
CurrencyType:
class CurrencyType extends Model
{
protected $table = 'currency_type';
protected $fillable = ['currency_type', 'currency_symbol', 'user_id'];
public function user()
{
return $this->belongsTo('App\User');
}
public function currency()
{
return $this->hasMany('App\current_currency');
}
}
User:
class User extends Model implements AuthenticatableContract,
AuthorizableContract,
CanResetPasswordContract
{
use Authenticatable, Authorizable, CanResetPassword;
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'users';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = ['name', 'email', 'password'];
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = ['password', 'remember_token'];
/**
* #param $value
*/
public function setPasswordAttribute($value)
{
$this->attributes['password'] = Hash::make($value);
}
/**
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function currentCurrency()
{
return $this->belongsToMany('User', 'CurrentCurrency', 'user_id', 'currency_id');
}
/**
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function currencyType()
{
return $this->hasMany('App\CurrencyType');
}
}
By this code i can get user information:
$all_records = CurrentCurrency::with(['user', 'currency_type'])->orderBy('id', 'DESC')->paginate(50);
foreach ($all_records as $key => $contents) {
echo $contents->user;
}
But i can not get currency_type, thats return null
RESULT:
{"id":3,"current_money":"333","user_id":1,
"created_at":"\u0622\u0630\u0631 20\u060c 1394",
"updated_at":"\u0622\u0630\u0631 20\u060c 1394",
"currency_id":1,"user":{"id":1,"name":"\u0645\u0647\u062f\u06cc",
"family":"\u067e\u06cc\u0634\u06af\u0648\u06cc","username":"mahdi","token":"",
"email":"pishguy#gmail.com",
"image_file_name":"","mobile_number":"09373036569",
"status":1,"created_at":"\u0622\u0630\u0631 20\u060c 1394",
"updated_at":"\u0622\u0630\u0631 20\u060c 1394"},
"currency_type":null}
You have to update the relation in CurrentCurrency as below:
return $this->belongsTo('App\CurrencyType','currency_id', 'id');
// where currency_id is foreign_key and id is otherKey referring to id of currency_type table
Also update your query to select user with CurrencyType as below :
$all_records = CurrentCurrency::with(array('user','currencyType'))->orderBy('id', 'DESC')->paginate(50);
http://laravel.com/docs/5.1/eloquent-relationships#updating-belongs-to-relationships
In file CurrencyType
return $this->hasMany('App\current_currency');
should be
return $this->hasMany('App\CurrentCurrency');
I can't Insert into this table and this drives me crazy
This is the error Msg I get
var_export does not handle circular references
open: /var/www/frameworks/Scout/vendor/laravel/framework/src/Illuminate/Database/Connection.php
* #param Exception $e
* #param string $query
* #param array $bindings
* #return void
*/
protected function handleQueryException(\Exception $e, $query, $bindings)
{
$bindings = var_export($bindings, true);
$message = $e->getMessage()." (SQL: {$query}) (Bindings: {$bindings})";
Here is my Full Mode
<?php
namespace Models;
use Illuminate\Database\Eloquent\Collection;
class Student extends \Eloquent
{
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'students';
/**
* The rules used to validate new Entry.
*
* #var array
*/
protected $newValidationRules = array(
'studentCode' => 'unique:students,code|numeric|required',
'studentName' => 'required|min:2',
'dateOfBirth' => 'date',
'mobile' => 'numeric'
);
/**
* Relation with sessions (Many To Many Relation)
* We added with Created_at to the Pivot table as it indicates the attendance time
*/
public function sessions()
{
return $this->belongsToMany('Models\Session', 'student_session')->withPivot('created_at')->orderBy('created_at', 'ASC');
}
/**
* Get Student Subjects depending on attendance,
*/
public function subjects()
{
$sessions = $this->sessions()->groupBy('subject_id')->get();
$subjects = new Collection();
foreach ($sessions as $session) {
$subject = $session->subject;
$subject->setRelation('student', $this);
$subjects->add($subject);
}
return $subjects;
}
/**
* Insert New Subject
* #return Boolean
*/
public function insertNew()
{
$this->validator = \Validator::make(\Input::all(), $this->newValidationRules);
if ($this->validator->passes()) {
$this->name = \Input::get('studentName');
$this->code = \Input::get('studentCode');
if ($this->save()) {
return \Response::make("You have registered the subject successfully !");
} else {
return \Response::make('An Error happened ');
}
} else {
Return $this->validator->messages()->first();
}
}
}
I am just trying to insert a new row with three Columns (I call the insertNew function on instance of Student)
1- ID automatically incremented
2- Special Code
3- Name
And I got this above Msg
What's I have tried till now :
removing all relations between from this model and other models
that has this one in the relation
Removed the validation step in insertNew()
Removed the all Input class calls and used literal data instead.
note that I use similar Inserting function on other Models and it works flawlessly
Any Comments , Replies are appreciated :D
Solution
I solved it and the problem was that I am accessing the validator
$this->validator = \Validator::make(\Input::all(), $this->newValidationRules);
And it was because I forgot that
/**
* The validator object.
*
* #var Illuminate\Validation\Validator
*/
protected $validator;
I had a similar problem. But to me, changing this code:
if ($this->validator->passes()) {
$this->name = \Input::get('studentName');
$this->code = \Input::get('studentCode');"
to this:
if ($this->validator->passes()) {
$this->setAttribute ("name" , \Input::get('studentName'));
$this->setAttribute ("code" , \Input::get('studentCode'));"
solved it.