I have some problem with laravel and protected $attributes and mutators.
I have user ranking with points. I want add to User Model another attribution with ranking Position.
In user model I have public function like this:
public function getRankPositionAttribute(){
$userPoints= Ranking::where('user_id','=',$this->id)->first();
$userPosition = Ranking::where('points','>',$userPoints->points)->count()+1;
return $userPosition;
}
I also set:
protected $attributes = array('RankPosition'='');
But it's not working (I don't see value like RankPosition in attributes). Strange thing is that when I add (for example) value like this:
protected $attributes =array('test'=>'yes');
Laravel also don't see test...
But when I add this:
protected $appends = array('RankPosition');
and in my controller I find all user and get response to json then in json response i see value like RankPosition with the correct value... :(
What Im doing wrong? Why "my laravel" skips protected $attributes?
Please help me.
This is because if you provide protected $attributes in your class then Laravel doesn't override it when the source of attributes are the table . Here the source of $attributes is database column.
But when you do something like this:
$user = new User;
then you will see a test attribute.
So to dynamically adding the attributes you should use appends property on the model.
Related
I have been trying to insert data using query into two columns of a table but there's something missing that its not sending data in the other column named booking_code.
It is inserting the booking_id into the table but not booking_code.
Here is the controller:
public function store(CreatePaymentRequest $request)
{
$input = $request->all();
$booking_id = $request->booking_id;
$booking_code = Booking::find($booking_id)->booking_code;
$this['booking_code'] = $booking_code;
$payment = $this->paymentRepository->create($input);
Flash::success('Payment saved successfully.');
return redirect(route('admin.payments.index'));
}
Please have a look at the Relevant Documentation Pages
You may also use the create method to save a new model in a single line. The inserted model instance will be returned to you from the method. However, before doing so, you will need to specify either a fillable or guarded attribute on the model, as all Eloquent models protect against mass-assignment by default.
That means that you have to set, in Model, which fields you will allow to be "mass-assigned".
In your case, it will looks something like
class Booking extends Model
(...)
{
protected $fillable = ['booking_code', (...)];
}
(...)
In the code you provided though, I can't see how you build an $input variable so maybe the issue is there? Maybe it's just some typo.
I have a controller which has a query such as this one:
$post = Post::find($id);
$comments = $post->comments;
Where a post has many comments and a comment belongs to one post. The comments model has an id,comment,tag field.
What I want to do is that for any query such as this one, the model returns the fields id, comment, tag and tag_translated, where the latter is just a translation of the tag using the Lang facade.
I could solve this by using a for on the controller which iterates over the $comments and adds the field, however Ill have to do that for every controller that requires the tag_translared field. Is there a way to ask the model to include such a field?
Add this in your Comment Model:
protected $appends = ['tag_translated'];
public function getTagTranslatedAttribute()
{
return 'the translated tag';
}
Hope this helps.
Yes there is? just add this to your Comment model
public function getTagTranslatedAttribute()
{
return Lang::methodYouWish($this->tag);
}
then you can access this property from comment instance
$comment->tag_translated;
EDIT
You can modify your toArray method, just add it to Comment class
protected $appends = ['tag_translated'];
and then
$comment->toArray();
I was facing the same issue, and you just need to add two things:
The first one is the appends field:
protected $appends = ['field'];
The second one is the "getter":
public function getFieldAttribute()
At the end of the method name you need to add the "Attribute" suffix, and that's it.
So I came across a weird issue while writing tests in laravel using factories. So this is a test I wrote:
/**
#test
*/
public function document_belongs_to_a_patent()
{
$patent = factory(Patent::class)->create();
$document = factory(Document::class)->create([
'documentable_id' => $patent->id,
'documentable_type' => 'patent'
]);
$this->assertArraySubset($patent->toArray(), $document->documentable->toArray());
}
So this should work, right because both should return the same thing and patent array should be equal or a subset of documentable array. But it was failing when I realised that there is an enum field in Patent model to which I am passing the value 1 but it was converted to the enum equivalent value in the database and when I tried document->documentable->toArray() it came back with the enum value rather than 1 which got me thinking how can make the model factory return the actual enum value and not the index number.
Top of the head I just fetched the patent just after creating it via the factory like so:
$patent = Patent::find($patent->id);
And it works well but it seems inconsistent. Is there a way to refresh models. I know we can refresh relationships of models but is there a way to do for the models themselves?
If you're strictly needing the change for API, you can do something cheeky with mutators like this.
https://laravel.com/docs/5.1/eloquent-serialization
Add this property. It tells Laravel that for special outputs only, it needs to append a non-database property.
protected $appends = ['documentable_type_name'];
Then you need some ways of knowing the language for the enum. You need an array, a #lang definition, etc. Here's a protected property solution that I am quite fond of in simple situations.
protected static $documentable_types = [ 'divorce', 'patent' ];
And then create this mutator on your Documentable model.
public function getDocumentableTypeName()
{
if ($this->documentable_type)
{
return static::$documentable_types[ $this->documentable_type ];
}
return null;
}
This changes your JSON output to look like this:
{
docuemntable_id : 555,
documentable_type : 1,
documentable_type_name : 'patent'
}
You can also hide the document_type field by adding this.
protected $hidden = ['documentable_type'];
And Laravel magic takes care of the rest. Hope that helps.
I am just learning laravel now. And I have this problem. I have passed 2 request parameters to my controller function. First request parameter holds an object value, but I converted it to a serialized form since the field of my table where it will be saved has a text datatype. The second request parameter holds a overall_total calculated value and it has a float datatype field. My problem is, how would I store it in my database? I have tried to use the create function but it returns an error. Some forums regarding this are not so clear. I just can't figure it out yet. Can somebody help me with this? Here are my codes.
function store
public function store(Request $request){
$serialize_po = serialize($request['purchase_orders']);
$overall_total = $request['overall_total'];
$purchase_orders_save = PurchaseOrder::create(?);
}
How would I save 2 parameters using create? or is there other way I can saved it?
Inside of $request['purchase_orders'] is shown in the image below
Inside of $request['overall_total'] is just a number. E.g. 310
My Database Table Structure is shown below
The create() function in Laravel accepts an associative array, where the array keys are the names of the columns, and the array values are the corresponding values for the columns.
So your store function might look something like this:
public function store(Request $request){
$serialize_po = serialize($request['purchase_orders']);
$overall_total = $request['overall_total'];
$purchase_orders_save = PurchaseOrder::create([
'purchase_orders' => $serialize_po,
'overall_total' => $overall_total
]);
}
One other thing to note is that as a safety precaution, Laravel does not allow the properties of a model to be filled in this fashion out of the box. You will need to list in your model using the $fillable property which keys you will allow to be filled by passing in an associative array. If you don't, you'll likely get a MassAssignmentException.
So in your model, you will likely need to have at least the following:
class PurchaseOrder extends Model
{
protected $fillable = ['purchase_orders', 'overall_total'];
}
There are more options and ways to do this, but that is the basic and typical scenario.
More info on using the create() method and handling mass assignment is available in the documentation: https://laravel.com/docs/5.2/eloquent#mass-assignment
Considering your model name is PurchaseOrder, you first need to create a new instance of it. Then, use the save method.
public function store(Request $request)
{
$purchaseOrder = new PurchaseOrder;
$purchaseOrder->overall_total = $request['overall_total'];
$purchaseOrder->purchase_orders = serialize($request['purchase_orders']);
$purchaseOrder->save();
}
See https://laravel.com/docs/5.2/eloquent#basic-inserts for more info.
Something like this :
DB::table('purchaseOrder')->insert(
['purchase_orders' => $serialize_po,'overall_total' => $overall_total]
);
See doc if you want to explore more.
The documentation doesn't go into much detail about saving data to mongodb.
I've installed a fresh install of laravel and set the up the mongo connections as in the docs, installed mongodb itself.
Created a model
use Jenssegers\Mongodb\Model as Eloquent;
class Notifications extends Eloquent {
protected $connection = 'mongodb';
protected $collection = 'notifications';
public static function foo()
{
return 'test returning from model';
}
}
And create a simple route to test
Route::get('notifiction' , function(){
$notifiction = new Notifications();
$arr = array('name' => 'John Doe');
$notifiction->save($arr);
});
But when I run localhost/mongo/public/notifiction I get Whoops, looks like something went wrong. I'm not sure what else needs doing to save information to mongodb through laravel?
This error is most likely to do with mass assignment. That is laravel treats every thing as unsafe before saving it to database. Thus we have to whitelist the fields we are trying to save.
The way we do this is in model. Lets say you are trying to save data in Users table using USER model. First open app/models/user.php and add following line:
class User extends Eloquent {
protected $fillable = ['name'];
}
Above, in fillable we are listing name as we want to save name from controller (if you have any additional data fill in the array). Now we can save data from controller.
Eg: User::create(array('name' => 'John')); will save name in Users collection. Please note the name of collection will be the name of the model unless specified otherwise.
[If this does not solve your problem, enable debug by going to app/config/app.php and setting debug =true. Find the error and try searching.]
You need not to do like model for SQL.
You try model like this
class User extends Moloquent {
protected $connection = 'mongodb';
protected $collection = 'collection1';
protected $fillable = ['_id','userName','passwd'];
}
You can try this to insert
DB::connection('mongodb')->collection('collection1')
->insert(array(
'_id' => 'H12345',
'userName' => 'Nithil',
'passwd' => 'qwoeuig'));
Using Moloquent is more convenient in using multiple DBS. For using Moloquent, you may register an alias for the MongoDB model by adding the following to the alias array in app/config/app.php:
'Moloquent' => 'Jenssegers\Mongodb\Model',
This will allow you to use the registered alias like:
class MyModel extends Moloquent {}
As OP has mentioned the error was due to
Did not installed the MongoDB PHP Library
Apart from that, to do mass assignment in Laravel, the fields should either be "white listed" or "black listed"
To whitelist the field(s) add
// name, age, username and email could be mass assigned
protected $fillable = ['name', 'age', 'username', 'email'];
To blacklist the field(s) add
// except _id everything could be mass assigned
protected $guarded = ['_id'];
to your model file