Skip to content

Instantly share code, notes, and snippets.

@MrJmpl3
Last active July 18, 2019 13:35
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MrJmpl3/578ab87ef3e46e0dd4bf5d77e537e71e to your computer and use it in GitHub Desktop.
Save MrJmpl3/578ab87ef3e46e0dd4bf5d77e537e71e to your computer and use it in GitHub Desktop.
ApiTrait - Trait helpers to Laravel API Resources
<?php
/**
* Copyright (c) 2018.
* Archivo desarrollado por Jose Manuel Casani Guerra bajo el pseudonimo de MrJmpl3
*
* Email: jmpl3.soporte@gmail.com
* Twitter: @MrJmpl3
* Pagina Web: https://mrjmpl3-official.es
*/
namespace App\Traits;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Validator;
/**
* Trait ApiTrait
*
* @package App\Traits
*/
trait ApiTrait
{
/**
* Sirve para seleccionar datos
*
* Ejemplo: /product?fields=column1,column2,column3,column4
*
* @param \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Builder $model
* @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model
*/
protected function fields($model)
{
/**
* Si existe la consulta de fields
*/
if (request()->has('fields')) {
/**
* Obtengo las columnas de la tabla del modelo
*/
$columns = Schema::getColumnListing($model->getModel()->getTable());
/**
* Obtengo la linea de consulta de fields
*/
$queryFields = explode(',', request()->get('fields'));
/**
* Arreglo de Select
*/
$selectColumns = [];
/**
* Recorro las columnas
*/
foreach ($columns as $column) {
/**
* Verifico si la columna esta asignada en el transform
*/
if (isset($model->getModel()->transforms[$column])) {
/**
* Verifico si la columna modificada esta en la consulta
*/
if (in_array($model->getModel()->transforms[$column], $queryFields)) {
$selectColumns[] = $column;
}
} else {
/**
* Verifico si la columna esta en la consulta
*/
if (in_array($column, $queryFields)) {
$selectColumns[] = $column;
}
}
}
/**
* Selecciono segun la consulta solo si el arreglo de Select no esta vacio
*/
if (count($selectColumns) > 0) {
$model = $model->select($selectColumns);
}
}
/**
* Retorno el modelo
*/
return $model;
}
/**
* Sirve para filtrar datos
*
* Ejemplo: /product?column=value&column2=value2
*
* @param \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Builder $model
* @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model
*/
protected function filter($model)
{
/**
* Obtengo las columnas de la tabla del modelo
*/
$columns = Schema::getColumnListing($model->getTable());
/**
* Obtengo el tipo de variable de cada columna
*/
$casts = $model->getCasts();
/**
* Recorro las columnas
*/
foreach ($columns as $column) {
/**
* Verifico si la columna esta asignada en el transform
*/
if (isset($model->getModel()->transforms[$column])) {
/**
* Verifico si la columna modificado existe en la peticion
*/
if (request()->has($model->getModel()->transforms[$column])) {
/**
* Ejecuto el where segun el casteo y dato enviado
*/
if (request()->input($model->getModel()->transforms[$column]) === '') {
$model = $model->where($column, '=', null);
} else {
switch ($casts[$column]) {
case 'int':
case 'integer':
$model = $model->where($column, '=', intval(request()->input($model->getModel()->transforms[$column])));
break;
case 'real':
case 'float':
case 'double':
$model = $model->where($column, '=', floatval(request()->input($model->getModel()->transforms[$column])));
break;
case 'string':
$model = $model->where($column, '=', strval(request()->input($model->getModel()->transforms[$column])));
break;
case 'bool':
case 'boolean':
$model = $model->where($column, '=', boolval(request()->input($model->getModel()->transforms[$column])));
break;
case 'date':
case 'datetime':
$model = $model->where($column, '=', Carbon::createFromFormat('d/m/Y', request()->input($model->getModel()->transforms[$column]), 'America/Lima')->format('Y-m-d'));
break;
}
}
}
} else {
/**
* Ejecuto el where segun el casteo y dato enviado
*/
if (request()->has($column)) {
if (request()->input($column) === '') {
$model = $model->where($column, '=', null);
} else {
switch ($casts[$column]) {
case 'int':
case 'integer':
$model = $model->where($column, '=', intval(request()->input($column)));
break;
case 'real':
case 'float':
case 'double':
$model = $model->where($column, '=', floatval(request()->input($column)));
break;
case 'string':
$model = $model->where($column, '=', strval(request()->input($column)));
break;
case 'bool':
case 'boolean':
$model = $model->where($column, '=', boolval(request()->input($column)));
break;
case 'date':
case 'datetime':
$model = $model->where($column, '=', Carbon::createFromFormat('d/m/Y', request()->input($column), 'America/Lima')->format('Y-m-d'));
break;
}
}
}
}
}
return $model;
}
/**
* Sirve para ordenar datos
*
* Ejemplo: /product?sort=-column1,column2
*
* Con prefijo negativo = desc
* Sin prefijo negativo = asc
*
* @param \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Builder $model
* @return \Illuminate\Database\Eloquent\Model
*/
protected function sort($model)
{
/**
* Si existe la consulta de sortBy
*/
if (request()->has('sortBy')) {
/**
* Obtengo la linea de consulta de sortBy
*/
$querySortBy = explode(',', request()->get('sortBy'));
/**
* Obtengo las columnas de la tabla del modelo
*/
$columns = Schema::getColumnListing($model->getTable());
/**
* Recorro las columnas
*/
foreach ($columns as $column) {
/**
* Verifico si la columna esta asignada en el transform
*/
if (isset($model->getModel()->transforms[$column])) {
/**
* En caso de que existe una query de la columna modificada
* Caso aparte: En caso de que existe una query de la columna pero con un '-'
*/
if (in_array($model->getModel()->transforms[$column], array_values($querySortBy))) {
$model = $model->orderBy($column, 'asc');
} elseif (in_array('-'.$model->getModel()->transforms[$column], array_values($querySortBy))) {
$model = $model->orderBy($column, 'desc');
}
} else {
/**
* En caso de que existe una query de la columna
* Caso aparte: En caso de que existe una query de la columna pero con un '-'
*/
if (in_array($column, array_values($querySortBy))) {
$model = $model->orderBy($column, 'asc');
} elseif (in_array('-'.$column, array_values($querySortBy))) {
$model = $model->orderBy($column, 'desc');
}
}
}
/**
* Retorno el modelo
*/
return $model;
} else {
/**
* Retorno el modelo con el orderBy basico
*/
return $model->orderBy('id', 'asc');
}
}
/**
* Sirve para paginar las respuestas
*
* Ejemplo: /product?paginate=true
* Ejemplo 2: /product?paginate=true&per_page=5
*
* @param \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Builder $model
* @return \Illuminate\Contracts\Pagination\LengthAwarePaginator|\Illuminate\Database\Eloquent\Model
* @throws \Illuminate\Validation\ValidationException
*/
protected function paginate($model)
{
/**
* Valor inicial de Paginas
*/
$perPage = 15;
/**
* Si existe la consulta
*/
if (request()->has('per_page')) {
/**
* Valido que este correcto el parametro
*/
$rulesPerPage = [
'per_page' => 'integer|min:2|max:50',
];
Validator::validate(request()->all(), $rulesPerPage);
/**
* Asigno el nuevo valor
*/
$perPage = intval(request()->get('per_page'));
}
/**
* Valor inicial de Paginacion
*/
$paginate = true;
/**
* Si existe la consulta
*/
if (request()->has('paginate')) {
/**
* Asigno el nuevo valor
*/
$paginate = (request()->input('paginate') === 'true');
}
/**
* Retorno el modelo final con/sin la paginacion conservando las demas queries en meta - links
*/
return $paginate ? $model->paginate($perPage)->appends(request()->all()) : $model->get();
}
}
<?php
/**
* Copyright (c) 2018.
* Archivo desarrollado por Jose Manuel Casani Guerra bajo el pseudonimo de MrJmpl3
*
* Email: jmpl3.soporte@gmail.com
* Twitter: @MrJmpl3
* Pagina Web: https://mrjmpl3-official.es
*/
namespace App;
use Illuminate\Database\Eloquent\Model;
use OwenIt\Auditing\Contracts\Auditable;
/**
* Class Product
*
* @package App
*/
class Product extends Model
{
/**
* @var string
*/
protected $table = 'products';
/**
* @var array
*/
protected $casts = [
'id' => 'integer',
'name' => 'string',
];
/**
* @var array
*/
public $transforms = [
'id' => 'code'
];
}
<?php
/**
* Copyright (c) 2018.
* Archivo desarrollado por Jose Manuel Casani Guerra bajo el pseudonimo de MrJmpl3
*
* Email: jmpl3.soporte@gmail.com
* Twitter: @MrJmpl3
* Pagina Web: https://mrjmpl3-official.es
*/
namespace App\Http\Controllers\Api\v1;
use App\Http\Resources\ProductCollection;
use App\Product;
use App\Traits\ApiTrait;
/**
* Class ProductosController
*
* @package App\Http\Controllers\Api
*/
class ProductsController extends Controller
{
use ApiTrait;
/**
* @return \Illuminate\Http\JsonResponse
* @throws \Illuminate\Validation\ValidationException
*/
public function index()
{
$products = new Product();
/**
* Filter data: /product?column=value&column2=value2
*/
$products = $this->filter($products);
/**
* Sort data: /product?sort=-column1,column2
* With the negative prefix = desc
* Without the negative prefix = asc
*/
$products = $this->sort($products);
/**
* Fields o Select data: /product?fields=column1,column2,column3,column4
*/
$products = $this->fields($products);
/**
* Paginate: /product?paginate=true
* PerPage: /product?paginate=true&per_page=5
*/
$products = $this->paginate($products);
/**
* Response
*/
return new ProductCollection($products);
}
}
<?php
/**
* Copyright (c) 2018.
* Archivo desarrollado por Jose Manuel Casani Guerra bajo el pseudonimo de MrJmpl3
*
* Email: jmpl3.soporte@gmail.com
* Twitter: @MrJmpl3
* Pagina Web: https://mrjmpl3-official.es
*/
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
/**
* Class Product
*
* @package App\Http\Resources
*/
class Product extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
/** @var \App\Product $this */
return [
$this->transforms['id'] => $this->id,
'name' => $this->name,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
}
@MrJmpl3
Copy link
Author

MrJmpl3 commented Apr 9, 2018

No hay manera de obtener los datos que son renombrados en un API Resources ..?

En fractal se puede obtener el transformer y obtener el valor original o editado ,,, Pero en API Resources ni idea ,,


Any idea , how to get the transformer from API Resource like Fractal?

@MrJmpl3
Copy link
Author

MrJmpl3 commented Apr 9, 2018

Se ha agregado un transform simple pero util para el Trait y las API Resources

@MrJmpl3
Copy link
Author

MrJmpl3 commented Apr 10, 2018

@fermi157
Copy link

hi, i just found your comment from the fb graph search, i am having hard time in understanding, please i tried to use thttps://sowdust.github.io/fb-search/he when ever i put the fb id of target i dont really know what to do, there three options down . if if copy URL what should i do with it . i kindly need your help or guidence . thank you so much ,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment