I have some problems with getting time on my app. I'm using laravel api to send informations to my React app.
I have controller like:
public function index(){
$user = auth()->user();
$servers = Server::where('clientid', $user->id)
->orderBy('id', 'desc')
->take(10)
->get();
if ($user) {
$reposne['result'] = true;
$reposne['servers'] = $servers;
} else {
return response()->json(['error' => 'Unauthorized'], 401);
}
return $reposne;
}
And it's successfuly returns what I need, like:
{
"result": true,
"servers": [
{
"id": 2512,
"clientid": 4,
"boxid": 23,
"ipid": 60,
"vazido": 1584355476,
"created_at": null,
"updated_at": null,
"status": "Active"
}
]
}
But as you see there is column vazido that is actyally giving a timestamp. How can I make this time to actual human format?
You can add a $casts attribute in your Server Model and Laravel will handle the rest for you.
Sever Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Server extends Model
{
protected $casts = [
'vazido' => 'datetime:Y-m-d',
];
}
In your model, You can use Eloquent Mutators to formate the date as following.
public function getVazidoAttribute($value)
{
return $value->format('Y-m-d');
}
By default, timestamps are formatted as 'Y-m-d H:i:s'.
I think your column type is int or string. So you can change the column type to timestamp or datetime.
$table->datetime('vazido')->change();
Or you can use mutator to convert the number to the datetime format, add this method to your Server Model:
public function getVazidoAttribute($value) {
return \Carbon\Carbon::createFromTimestamp($value)->format('Y-m-d H:i:s');
}
Related
I tried to display data in the database, the date format in the database is like 2020-10-11T17: 22: 29.000000Z ", how can i change it just to 2020-10-11, or 11 December 2020 ?
This is my controller
public function get_all_artikel(){
$data = ArtikelKonten::select(
'artikel_kategori.nama as kategori','artikel_konten.*')
->join('artikel_kategori','artikel_kategori.id','artikel_konten.id_kategori')
->get();
if ($data){
return response()->json([
'status' => true,
'artikel' => $data,
],200);}
else{
return response()->json([
'status' => false,
'message' => 'No Artikel were found'
],404);}
}
This is my model
class ArtikelKonten extends Model
{
protected $table = 'artikel_konten';
protected $fillable = ['id_kategori', 'gambar', 'tag_program', 'nm_program', 'judul', 'preview', 'konten'];
const CREATED_AT = 'created';
const UPDATED_AT = 'modified';
}
And this is the result
{
"status": true,
"artikel": [
{
"kategori": "Program",
"id": 4,
"id_kategori": "2",
"tag_program": "2",
"nm_program": "Zakat Mall",
"gambar": "http://127.0.0.1:8000/storage/photos/1/article1.png",
"judul": "Mengenalkan Zakat Kepada Anak",
"preview": null,
"konten": null,
"created": "2020-12-10T07:24:50.000000Z",
"modified": "2020-12-10T08:06:07.000000Z"
},
{
"kategori": "Berita",
"id": 10,
"id_kategori": "1",
"tag_program": "4",
"nm_program": "Jumat Barokah",
"gambar": "http://127.0.0.1:8000/storage/photos/1/article2.png",
"judul": "Suplemen Iman Ditengah Pandemi",
"preview": null,
"konten": null,
"created": "2020-12-11T20:44:25.000000Z",
"modified": "2020-12-11T20:44:25.000000Z"
},
{
"kategori": "Program",
"id": 11,
"id_kategori": "2",
"tag_program": "2",
"nm_program": "Zakat Mall",
"gambar": "http://127.0.0.1:8000/storage/photos/1/article3.png",
"judul": "Menumbuhkan Semangat Berzakat Umat",
"preview": null,
"konten": null,
"created": "2020-12-11T20:46:23.000000Z",
"modified": "2020-12-11T20:46:23.000000Z"
}
]
}
I just wana change the "created": "2020-12-11T20:46:23.000000Z", to "create":"2020-12-11", thanks for your answer guys :)
Laravel 7 uses a new date serialization format when using the toArray or toJson method on Eloquent models.
If you would like to keep using the previous behavior you can override the serializeDate() method on your model :
use DateTimeInterface;
protected function serializeDate(DateTimeInterface $date)
{
return $date->format('Y-m-d');
}
See the official upgrade doc here [7.x]
use date() for clear date and time formate
date('d-m-Y', strtotime($value->created));
Eloquent Model has a property called cast to cast the output of the query to the desired format, in your case just cast your date columns like in doc:
class ArtikelKonten extends Model
{
protected $casts = [
'created' => 'datetime:Y-m-d','modified' => 'datetime:Y-m-d'
];
}
Laravel allows to specify the format in which datetime fields should be converted when serialized to array or json
Define $casts property on the model
protected $casts = [
'created_at' => 'datetime:Y-m-d',
'updated_at' => 'datetime:Y-m-d',
];
Read more : https://laravel.com/docs/8.x/eloquent-mutators#date-casting
you cab use accessor for create_at and put this code in your model:
public function getCreatedAtAttribute($date)
{
return Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $date)->format('Y-m-d');
}
First way
Just add to the model:
protected function asDateTime($value)
{
return parent::asDateTime($value)->format('d/m/y');
}
Second way
You can individually customize the format of Eloquent date and datetime casting:
protected $casts = [
'created_at' => 'date:Y-m-d',
'updated_at' => 'datetime:Y-m-d H:00',];
A few links that helped me to answer
link one
A few links that helped me to answer link two
PHP Laravel Framework
Laravel Framework
:
8.42.1
Date tested
:
22 May 2021
PHP version
:
7.3.8
Database
:
MariaDB 10.5.8
OS
:
MacOS 10.13.6 High Sierra
Question
How to transform or change a table column's value/result on the fly e.g. format the timestamp into a date (y-m-d h:i:s) format?
Answer
Using Laravel Eloquent: Mutators & Casting helps the user to transform data values on the fly by defining them in the Model property.
Introduction
Accessors, mutators, and attribute casting allow you to transform Eloquent attribute values when you retrieve or set them on model instances. For example, you may want to use the Laravel encrypter to encrypt a value while it is stored in the database, and then automatically decrypt the attribute when you access it on an Eloquent model. Or, you may want to convert a JSON string that is stored in your database to an array when it is accessed via your Eloquent model.
Attribute Casting
Attribute casting provides functionality similar to accessors and mutators without requiring you to define any additional methods on your model. Instead, your model's $casts property provides a convenient method of converting attributes to common data types.
My table scema
My table data
My front result (before cast)
My front result (post cast)
My model file
<?php
// app/Models/Post.php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use HasFactory;
protected $fillable = [
'title', 'description'
];
// I've added this because I want to convert timestamp to 'y-m-d' on the fly
protected $casts = [
'created_at' => 'datetime:Y-m-d',
'updated_at' => 'datetime:Y-m-d'
];
}
My controller (I've created controller inside a sub folder 'API')
<?php
// app/Http/Controllers/API/PostController.php
namespace App\Http\Controllers\API;
use App\Http\Controllers\Controller;
use App\Models\Post;
use Illuminate\Http\Request;
use Validator;
class PostController extends Controller
{
// all posts, I'm calling this be the default
public function index()
{
$posts = Post::all()->toArray();
return array_reverse($posts);
}
}
My routes
<?php
// routes/api.php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\API\PostController;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
Route::get('posts', [PostController::class, 'index']);
Route::group(['prefix' => 'post'], function () {
Route::post('add', [PostController::class, 'add']);
Route::get('edit/{id}', [PostController::class, 'edit']);
Route::post('update/{id}', [PostController::class, 'update']);
Route::delete('delete/{id}', [PostController::class, 'delete']);
});
My view (Vue)
<template>
<div>
<h3 class="text-center">All Posts</h3><br/>
<table class="table table-bordered table-responsive">
<thead>
<tr>
<th>ID</th>
<th>Title</th>
<th>Description</th>
<th>Created At</th>
<th>Updated At</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr v-for="post in posts" :key="post.id">
<td>{{ post.id }}</td>
<td>{{ post.title }}</td>
<td style="width: 30%">{{ post.description }}</td>
<td>{{ post.created_at }}</td>
<td>{{ post.updated_at }}</td>
<td>
<div class="btn-group" role="group">
<router-link :to="{name: 'edit', params: { id: post.id }}" class="btn btn-primary">Edit
</router-link>
<button class="btn btn-danger" #click="deletePost(post.id)">Delete</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
data() {
return {
posts: []
}
},
created() {
this.axios
.get('/api/posts')
.then(response => {
this.posts = response.data;
});
},
methods: {
deletePost(id) {
this.axios
.delete(`/api/post/delete/${id}`)
.then(response => {
let i = this.posts.map(item => item.id).indexOf(id); // find index of your object
this.posts.splice(i, 1)
});
}
}
}
</script>
I'm quite new to Laravel and I was not able to find the answer to this problem neither on Laravel docs, nor here.
I guess it's just a matter of how to search for it, cause I'm pretty sure it's a common case.
I have two models in relationship (this is a simplified case), I retrieve the info I need through a Resource file, but I'm not able to understand how to properly store or update info.
Here's a code example:
Models\Company.php
class Company extends Model
{
protected $fillable = [
'name', 'blablabla', 'country_id', 'blablabla2',
];
public function country() {
return $this->belongsTo(Country::class);
}
}
Models\Country.php
class Country extends Model
{
protected $fillable = [
'code', 'name', 'prefix', 'tax_code_id',
];
public function companies() {
return $this->hasMany(Company::class);
}
}
Then I have a CompanyController file to manage API requests:
Controllers\CompanyController.php
class CompanyController extends BaseController
{
public function index()
{
$companies = Company::paginate();
$response = CompanyResource::collection($companies)->response()->getData(true);
return $this->sendResponse($response, 'Companies retrieved successfully');
}
public function store(Request $request)
{
$input = $request->all();
$validator = Validator::make($input, $this->validation_rules);
if($validator->fails()){
return $this->sendError('Validation error.', $validator->errors());
}
$company = Company::create($input);
return $this->sendResponse($company->toArray(), 'Company added successfully.');
}
}
...
public function update(Request $request, Company $company)
{
$input = $request->all();
$validator = Validator::make($input, $this->validation_rules);
if($validator->fails()){
return $this->sendError('Validation error.', $validator->errors());
}
$company->update($input);
return $this->sendResponse($company->toArray(), 'Company updated successfully.');
}
And here the CompanyResource I'm using to display info as I need.
Resources/CompanyResource.php
class CompanyResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'blablabla' => $this->blablabla,
'country' => $this->country,
'blablabla2' => $this->blablabla2,
];
}
}
So when retrieving Companies (or single company) I get a nested JSON:
{
"id": "1",
"name": "something",
"blablabla": "blablabla",
"country": {
"id": "100",
"code": "MA",
"name": "Mars",
"prefix": "123",
"tax_code_id": "#$%"
},
"blablabla2": "blablabla2"
}
If I create or update a new company I send a payload that has the same structure of what I'm getting above, but if I edit country id value my company model doesn't get it.
PUT Api/companies/1
{
"name": "something",
"blablabla": "blablabla3",
"country": {
"id": "200",
"code": "JU",
"name": "Jupiter",
"prefix": "456",
"tax_code_id": "#=%"
},
"blablabla2": "blablabla2"
}
I'm expecting to update country_id field in companies table for record 1 so that it matches payload (so going from 100 to 200), but it's not happening.
I could edit frontend logic in order to send only country_id in payload since I'm not going to update countries table and all that additional info is redundant, but I'd like to know how to manage it in controller with Laravel.
Would you mind helping me? Thanks in advance.
If you want it to work with the code now, you need to have country_id in the root JSON object you are sending. As this is the way you would fill the id. This is not the best approach in my opinion, but this is why your update is not working at the moment.
{
"name": "something",
"blablabla": "blablabla3",
"country_id": 200,
...
I actually like the approach of sending complete objects. Commonly to fill id's is not good, as it can interfere with the way relations work. Laravel will set your relationships when you associate, if not you are not guaranteed to have the correct relationship after the fill.
Therefor i would fetch out the id and associate the country object with the company. In a logic similar to this.
// only fill non relation fields, fill used as save is needed after associate()
$company->fill($request->only(['name', 'blabla']));
$company->country()->associate(Country::find($request->get('country')['id']));
//associate does not save
$company->save();
I wrote a gist for this years ago that can relate any two models regardless of their relationship type. You just need to supply it with the name of the relationship method: https://gist.github.com/kmuenkel/055f107139d904e30810bf53750d9c6e
I'm trying to remove created_at and updated_at before returning response to api . I want to removie these field from both Place_Type and Places
how can I do that? :
I tried : unset(placetypes) but it didn't work
This is my Code:
public function places()
{
$placeType = PlaceType::with('places')->where('id', 1)->get();
return response()->json(['placeType' => $placeType]);
}
The request result:
"placeType": [
{
"id": 1,
"name": "Moriah O'Conner",
"icon": "https://picsum.photos/200/300",
"status": 1,
"created_at": "2019-12-14 18:23:19",
"updated_at": "2019-12-14 18:23:19",
"places": [
{
"id": 1,
"name": "Linda Leffler",
"description": "Alice's shoulder, and it set to work, and very soon came to ME, and told me he was in the air. She did it so VERY remarkable in that; nor did Alice think it would feel very queer to ME.' 'You!' said.",
"icon": "https://picsum.photos/200/300",
"image_name": "https://picsum.photos/200/300",
"rating": 2,
"longitude": -53.389979,
"latitude": 19.633458,
"availability": 1,
"status": 1,
"place_type_id": 1,
"created_at": "2019-12-14 18:23:19",
"updated_at": "2019-12-14 18:23:19"
},
{
"id": 2,
"name": "Lauren Cartwright",
"description": "I should say \"With what porpoise?\"' 'Don't you mean by that?' said the King. 'I can't remember half of anger, and tried to look at it!' This speech caused a remarkable sensation among the leaves.",
"icon": "https://picsum.photos/200/300",
"image_name": "https://picsum.photos/200/300",
"rating": 1,
"longitude": -38.117034,
"latitude": -32.248637,
"availability": 1,
"status": 1,
"place_type_id": 1,
"created_at": "2019-12-14 18:23:19",
"updated_at": "2019-12-14 18:23:19"
}...,
}
Add the fields to the $hidden array:
// Model
protected $hidden = ['created_at', 'updated_at'];
There are different methods you can use.
Method 1 : Fetch only required fields from the database
You can use select() method for retrieving only required fields from db. Hence you can omit the unnecessary fields.
$placeType = PlaceType::with(['places' => function ($query) {
$query->select('id', 'name', 'description', 'icon',
'image_name', 'rating', 'longitude', 'latitude',
'availability', 'status', 'place_type_id'); //timestamps excluded
}])
->select('id', 'name', 'icon', 'status') //timestamps excluded
->where('id', 1)
->get();
return response()->json(['placeType' => $placeType]);
This code will output only specified fields both in the parent model (placetype) and child model (places).
If you use these customized select query more than once and writing all field names multiple time is difficult, then you could use model scope like the following.
PlaceType Model
// add all columns from your table
protected $columns = ['id', 'name', 'icon', 'status', 'created_at', 'updated_at'];
public function scopeExclude($query,$value=[])
{
return $query->select( array_diff( $this->columns,(array) $value) );
}
Place Model
// add all columns from your table
protected $columns = ['id', 'name', 'description', 'icon', 'image_name',
'rating', 'longitude', 'latitude', 'availability',
'status', 'place_type_id', 'created_at', 'updated_at'
];
public function scopeExclude($query,$value=[])
{
return $query->select( array_diff( $this->columns,(array) $value) );
}
Then you could remove unwanted fields like the following
$placeType = PlaceType::with(['places' => function ($query) {
$query->exclude(['created_at', 'updated_at']); //exclude fields from Place model
}])
->exclude(['created_at', 'updated_at']) //exclude fields from PlaceType model
->where('id', 1)
->get();
Courtesy : This SO answer by #Razor
Method 2 : Hide your column from serialization where you need
You can hide your column from serialization using laravel's makeHidden() method. In this method after fetching rows with all fields, you are making the specified fields as hidden. [Please note that the excluded variables won't appear on json but may visible on dump].
//get rows with all fileds (except hidden)
$placeType = PlaceType::with('places')->where('id', 1)->get();
//making timestamps hidden in child model's rows
$placeType->places->makeHidden(['created_at','updated_at']);
//making timestamps hidden in parent model's rows
$placeType->makeHidden(['created_at','updated_at']);
return response()->json($placeType);
Courtesy : This SO answer by #sajed
Method 3 : Using Hidden property
If the timestamps are unnecessary in most of the time in the app, you could use the model's hidden property.
PlaceType Model & Place Model
protected $hidden = ['created_at', 'updated_at'];
Hope this will be helpful. 🤗
1) You just need to declare public $timestamps = false; in every model you want to hide it.
2) You can also disable timestamps by removing $table->timestamps() from your migration.
3) Declare protected $hidden = ['created_at', 'updated_at']; in your model.
In case you want to remove timestamps from model, as mentioned before, place this in your Model:
public $timestamps = false;
Also create a migration with following code in the up() method and run it:
Schema::table('your_table', function (Blueprint $table) {
$table->dropTimestamps();
});
You can use $table->timestamps() in your down() method to allow rolling back.
or in model
const UPDATED_AT = null;
const CREATED_AT = null;
Assuming that $placeType is array, you can use this recursive function:
function removeTimeStampValues($array)
{
if(array_key_exists('created_at', $array) && array_key_exists('updated_at', $array)) {
unset($array['created_at']);
unset($array['updated_at']);
}
foreach ($array as $key => $value) {
if(is_array($value)) {
$array[$key] = recursiveRemoveTimeStampValue($value);
}
}
return $array;
}
If you don't want these columns, you can do as others said based on the documentation (under "Timestamps" title).
But if you need these column and just don't want them in the json response, you can use resource. See the documentation.
When I call eloquent:
$user = User::where('idUser', 1)->with(['privilege'])->first()->toArray();
It gives me:
{
"idUser": 1,
"name": "UserName",
"email": "UserName#gmail.com",
"image": "https://image.com",
"createdAt": "2019-05-07 15:43:47",
"privilege": {
"idPrivilege": 1,
"name": "user"
}
}
When I call Eloquent:
$user = User::where('idUser', 1)->with(['privilege:name'])->first()->toArray();
Element privilege in json is set to null, but when I call:
$user = User::where('idUser', 1)->with(['privilege:idPrivilege,name'])->first()->toArray();
It is as same as first call. How can I set element privilege to f.e. user (I just want a simple value instead of the full object of Privilege)?
I can use something like:
$user['privilege'] = $user['privilege']['name'];
But this one does not look so nice!
Using resource:
public function toArray($request)
{
return [
'idUser' => $this->idUser,
'name' => $this->name,
'email' => $this->email,
'privilege' => $this->privilege['name'],
'createdAt' => $this->created_at,
];
}
In controller:
$user = User::where('idUser', 1)->with('privilege')->first();
return UserResource::make($user);
Gives:
{
"data": {
"idUser": 1,
"name": "UserName",
"email": "UserName#gmail.com",
"privilege": "user",
"createdAt": "2019-05-07 15:43:47"
}
}
How can i just return object instead of data{object} ?
Try without the backets:
$user = User::where('idUser', $id)->with('privilege:name')->first()->toArray();
or this:
$user = User
::where('idUser', $id)
->with(['privilege' => function($query) {
return $query->select('name');
}])
->first()
->toArray();
But then, you could customize the response to return to your view using API Resources. With this, you can have many different resources to use on the same elements and format the response to any of your needs.
As stated in HCK's answer, you could use
$user = User
::where('idUser', $id)
->with(['privilege' => function($query) {
return $query->select('name');
}])
->first()
->toArray();
To get what you need. Now, if you are already using API Resources, and want to remove the outter data object, you can add the following in your AppServiceProvider boot method:
use Illuminate\Http\Resources\Json\Resource;
class AppServiceProvider extends ServiceProvider
{
/**
* Perform post-registration booting of services.
*
* #return void
*/
public function boot()
{
Resource::withoutWrapping(); // With this, your resources won't have the
// outter data wrapping
}
}
Just take a look at the docs!
I'm still a newbie in laravel.
I have this result in JSON and I want to get the 'bio' inside the 'user_details'.
{
"id": 1,
"name": "Jasper Mendiola",
"username": "jasperduane77",
"created_at": "2017-07-22 10:11:04",
"updated_at": "2017-07-22 10:11:04",
"userType": "Administrator",
"user_details": {
"user_id": 1,
"profile_pic": null,
"bio": "frustrated software blahblahblah"
}
I tried this code in my view
{{$user->user_details->bio}}
but Im having the error
> Trying to get property of non-object
This is my laravel Controller:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
use App\UserDetail;
use DB;
class UsersController extends Controller
{
public function __construct() {
$this->middleware('auth');
}
public function index()
{
//
$user_id = auth()->user()->id;
$user = User::with('userDetails')->find($user_id);
/**** When I enter this code, I get the error
return view('profile.index')->with('user', $user); */
return json_encode($user);
}
}
How do you exactly do this? Help is deeply appreciated.
You should use like this:
<?php
$jsonData = '{
"id": 1,
"name": "Jasper Mendiola",
"username": "jasperduane77",
"created_at": "2017-07-22 10:11:04",
"updated_at": "2017-07-22 10:11:04",
"userType": "Administrator",
"user_details": {
"user_id": 1,
"profile_pic": null,
"bio": "frustrated software blahblahblah"
}
}';
$josnObj = json_decode($jsonData);
echo $josnObj->user_details->bio;//frustrated software blahblahblah
?>
If you want to send JSON response
In your controller, just replace return json_encode($user); with return $user;
It will automatically send $user as json response. If you will use return json_encode($user); it will just send json response in string format and you will need to convert this string into array or object using json_decode() in your view.
If you want to send data to view
then in your controller:
return view('profile.index', ['user' => $user]);
Then in your view:
{{$user->user_details->bio}}
You're returning a json string so that would be cool for an API request. The way laravel does this is using the view() so we can render a blade template. In that case you should do something like this:
Controller code:
return view('users.index', [ 'user' => $user ]);
In here you would need a blade file inside of views/users/index.blade.php and in there you can call the {{$user->user_details->bio}} because you're still using the User model instead of a json "string".