Use one method to all messages from db - php

I have a tables which I want to use one or more methods to all result from db. This method can change #hashtags to links, bbcode to html tags, etc. Let's assume that I have this query:
$query = Comments::orderBy('created_at', 'desc')->get();
Comments table has a comment column where user can use emoticons bbcode, etc. This query returns a few of results. How I can use method on column? If I have one result is simple:
$query = Posts::find(1);
$desc = myMethod($query->desc);

I assumne you want to format your eloquent attributes? have a look at https://laravel.com/docs/5.8/eloquent-mutators
and if you don't want to save your formatted data on db. you can just use the Accessor by defining it. for example please see below
// on your model you just need to create new methods
// with `get` as prefix and `Attribute` as suffix
public function getBbcToHtmlAttribute() {
return myMethod($query->desc);
}
please note that get and Attribute on your method name is required (e.g getMyNewAccessorAttribute`
after that you need to add casts property. if you already have casts property you just add it to the array if you dont have casts property you need to define it.
protected $casts = [
'BbcToHtml'
];
and then you can use it anywhere on your model instance.
$query = Posts::find(1);
$desc = $query->bbctohtml;

As MarkB has said, you would need to use a mutator, create a helper class that can take any input and produce the correct html code for your bbcode. Then you would create a mutator on your model and use that instead of the field where the bbcode text is.

Related

Catch and save elements in Laravel, not by primaryKey

I need to get an element from the database, but I can not get it by the FIND method, since FIND only finds it by the primaryKey and what I need is not by my primaryKey. So I did like this:
$user = Pac::find($request->pac_id);
$element = query()->where('med_cart', $user->pac_id)->get();
$element->med_obs = $request->med_obs;
$element->save(); // error
Now I need to save this element, however, I can not use the SAVE method, as I believe it is fully connected with FIND and FINDORFAIL (if anyone knows, explain to me which methods I can use the SAVE method).
How can I save them the way I did? Or is there some other way to do it?
Because I need to get the element with a data other than the primaryKey and then save it, then I can not use FIND or FINDORFAIL, I think.
The function ->find() returns an Eloquent Model instance and you can then call ->save() on the model instance.
You're using ->get() which returns a Collection.
To update your query (that may target one or more entries) just perform the update statement directly from the QueryBuilder by replacing ->get() with ->update(['med_obs' => $request->med_obs]).
Be aware that when doing this you are now using Fluent queries, instead of eloquent. This means that any logic you may have defined in the boot function of your model is not evaluated.
If you are certain that you only have a single result you can append ->first() to your query, which will return a Model of the first result that matches your ->where clause. You can then call ->save() on it:
$user = Pac::find($request->pac_id);
$element = query()->where('med_cart', $user->pac_id)->first();
$element->med_obs = $request->med_obs;
$element->save();

Laravel's eloquent post-processing query

I am using PostgreSQL + PostGIS setup, and I want to fetch geom column from database as GeoJSON. I know I can do that using ST_AsGeoJSON() function. So i use this code to fetch all countries:
$countries = Country::select(["id", "name", DB::raw("ST_AsGeoJSON(geom) AS geom")])->get()
However, I end up with $countries[i]->geom being a string so I need to have for loop to do this:
$countries[i]->geom = json_decode($countries[i]->geom);
I would like to move this line of code to the Eloquent Model so I do not have to worry if I forget to decode column or not. Is there a method I should override or any way to add this special functionality to my Country model?
Add the following to your model
protected $casts = [
'geom' => 'array',
];
https://laravel.com/docs/5.3/eloquent-mutators#array-and-json-casting
You can use mutator/accessor to override or to decode the values in your model. So in your model do the following.
public function getGeomAttribute()
{
return json_decode($this->attributes['geom']);
}
With this you can access geom at different part of your application without decoding it.

How to save multiple request parameters in laravel 5.2 ?

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.

Excluding Laravel appends values from model results

Laravel has the option to add an $appends array to each model making additional values automatically available as if they are database attributes by adding accessors for each.
This is normally pretty handy, except in this case I need to ONLY get the fields I put into select() because DataTables is expecting only what I send to it.
Example:
Item::select(['image', 'name', 'color']);
Will return appended fields after color in the attributes.
How do I force the exclusion of the appends values when returning results?
Or alternatively, how do I get DataTables to ignore certain attributes?
Not sure which is the least time costly route.
Currently using yajra/laravel-datatables package to send data to the jQuery DataTables AJAX request.
You can call each function in the collection object and then use setHidden method to exclude the unwanted fields like this
$item= Item::select(['image', 'name', 'color'])->get()->each(function($row){
$row->setHidden(['appendedField1', 'appendedField2']);
});
And for the yajra/laravel-datatables you can use something like
$item= Item::select(['image', 'name', 'color']);
return Datatables::of($item)->remove_column('appendedField1');
To solve this I added this method to my Item model:
public static function getAppends()
{
$vars = get_class_vars(__CLASS__);
return $vars['appends'];
}
Then used the following code in the controller:
$items = Item::select(['image', 'name', 'color']);
$DT = Datatables::of($items);
call_user_func_array([$DT, 'removeColumn'], Item::getAppends()); // Has to be called this way with yajra/laravel-datatables-oracle v3.* if passing an array.
return $DT->make(true);

Mapping data in Laravel to a JSON object

I'm trying to convert data retrieved from my Laravel model to a JSON object as outlined in the Backbone docs.
My problem is that when I encode the data all I get are the public properties and none of the (protected) attributes - the ones I actually want. This is how I go about it:
Controller
$movie = Movie::with('awards.award', 'customAwards.awardCustom', 'cast.person', 'imdb.rottenTomatoes')->find($id);
return View::make('movie')->with(array(
'movie' => $movie
));
View
<script type="text/javascript">
DS.Resources.Movie = {{json_encode($movie)}};
</script>
DS.Resources.Movie output
{
"timestamps":false,
"incrementing":true,
"exists":true
}
If I var_dump $movie I can see the protected attributes like title, year, a cast collection, awards collection etc. How do I access these properties and map them to my JSON object?
In Eloquent, you should use ->toJson() as it correctly only gets the model's attributes, rather than general class properties. Similarly, it'll get your relationships if you used a ->with() I think.
If you don't want certain attributes to come out in the JSON (like password fields) you can specify an array in your class called hidden, see the docs.
You should unprotect them in your model.
Also you should realize you can use ->toJson() on your model instead of json_encode'ing it.

Categories