I am beginner in Laravel. In my project I use repository pattern and Laravel 7.
I have this controller:
class PageController extends Controller
{
protected $model;
/**
* PageController constructor.
* #param PageRepositoryInterface $repository
*/
public function __construct(PageRepositoryInterface $repository)
{
$this->model = $repository;
}
/**
* #param Request $request
* #return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function index(Request $request)
{
if ($request->input('query') != "") {
$pages = $this->model->search($request->input('query'), 'id', 'asc', [], 30);
} else {
$pages = $this->model->listWithPaginate('id', 'desc', [], 30);
}
return view('admin.pages.list', ['pages' => $pages]);
}
/**
* #return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function create()
{
return view('admin.pages.view');
}
/**
* #param PageRequest $request
* #return \Illuminate\Http\RedirectResponse
*/
public function store(PageRequest $request)
{
if ($request->isMethod('post')) {
$data = [
'title' => $request->input('title'),
'description' => $request->input('description') ?? $request->input('title'),
'keywords' => $request->input('keywords') ?? $request->input('title'),
'content' => $request->input('content'),
'enable' => $request->input('enable') ?? 0,
'slug' => Str::slug($request->input('title'), '-')
];
$this->model->create($data);
return redirect()->route('page.index')->with('success', __('messages.record_save_info'));
}
}
/**
* #param int $id
* #return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function edit(int $id)
{
Cache::forget("page.{$id}");
return view('admin.pages.view', ['page' => $this->model->findOrFail($id)]);
}
/**
* #param PageRequest $request
* #param int $id
* #return \Illuminate\Http\RedirectResponse
*/
public function update(PageRequest $request, int $id)
{
if ($request->isMethod('put')) {
$data = [
'title' => $request->input('title'),
'description' => $request->input('description'),
'keywords' => $request->input('keywords'),
'content' => $request->input('content'),
'enable' => $request->input('enable') ?? 0,
'slug' => Str::slug($request->input('title'), '-')
];
$this->model->update($data, $id, 'id');
return redirect()->route('page.index')->with('success', __('messages.record_edit_info'));
}
}
/**
* #param Request $request
* #param int $id
* #return \Illuminate\Http\RedirectResponse
*/
public function destroy(Request $request, int $id)
{
if ($request->isMethod('delete')) {
$this->model->delete($id);
return redirect()->route('page.index')->with('success', __('messages.record_remove_info'));
}
}
}
and CachingBaseRepository
abstract class CachingBaseRepository implements RepositoryInterface
{
use ScopeActiveTrait;
protected $model;
protected $cacheKey;
protected $cacheTime;
public function all()
{
return Cache::remember($this->cacheKey.'.all', $this->cacheTime, function () {
return $this->model->get();
});
}
public function allEnables()
{
return Cache::remember($this->cacheKey.'.enables', $this->cacheTime, function () {
return $this->model->active()->get();
});
}
public function list(string $orderByColumn, string $orderBy = 'desc', array $with = [])
{
return Cache::remember($this->cacheKey.'.list', $this->cacheTime, function () use($with, $orderByColumn, $orderBy) {
return $this->model->with($with)
->orderBy($orderByColumn, $orderBy)
->get();
});
}
public function listWithPaginate(string $orderByColumn, string $orderBy = 'desc', array $with = [], int $perPage = 10)
{
return Cache::remember($this->cacheKey.'.listWithPaginate', $this->cacheTime, function () use($with, $orderByColumn, $orderBy, $perPage) {
return $this->model->with($with)
->orderBy($orderByColumn, $orderBy)
->paginate($perPage)->appends(request()->query());
});
}
public function create(array $data): int
{
Cache::forget($this->cacheKey);
Cache::forget($this->cacheKey.'.all');
Cache::forget($this->cacheKey.'.enables');
Cache::forget($this->cacheKey.'.list');
Cache::forget($this->cacheKey.'.listWithPaginate');
return $this->model->create($data)->id;
}
public function update(array $data, int $id, string $attribute = 'id'): void
{
$this->model->where($attribute, '=', $id)->update($data);
Cache::forget($this->cacheKey);
Cache::forget($this->cacheKey.".{$id}");
Cache::forget($this->cacheKey.'.all');
Cache::forget($this->cacheKey.'.enables');
Cache::forget($this->cacheKey.'.list');
Cache::forget($this->cacheKey.'.listWithPaginate');
}
public function delete(int $id): void
{
$this->model->destroy($id);
Cache::forget($this->cacheKey);
Cache::forget($this->cacheKey.'.all');
Cache::forget($this->cacheKey.'.enables');
Cache::forget($this->cacheKey.'.list');
Cache::forget($this->cacheKey.'.listWithPaginate');
}
public function find(int $id)
{
return Cache::remember($this->cacheKey.".{$id}", $this->cacheTime, function () use ($id) {
return $this->model->find($id);
});
}
public function getModel()
{
return Cache::remember($this->cacheKey.".all", $this->cacheTime, function (){
return $this->model;
});
}
public function findOrFail(int $id)
{
return Cache::remember($this->cacheKey.".{$id}", $this->cacheTime, function () use ($id) {
return $this->model->findOrFail($id);
});
}
}
I have problem with paginate. When I go to pagination 2,3,7 or 10 - I always see the same as on page 1.
Is my code optimal? Can duplication be replaced - one function (I have remove in controller - in edit too):
:: Cache forget ($ this-> cacheKey);
:: Cache forget ($ this-> cacheKey.. 'All');
:: Cache forget ($ this-> cacheKey. '. Enables');
:: Cache forget ($ this-> cacheKey.. 'Letter');
:: Cache forget ($ this-> cacheKey. '. ListWithPaginate');
some one function?
That is because when you call first page it is cached, on second page since the key is not changed the cache assume that you want cached version and returns page 1.
One way will be to update tag depending on input:
public function listWithPaginate(string $orderByColumn, string $orderBy = 'desc', array $with = [], int $perPage = 10)
{
$tag = sprintf('%s.listWithPaginate.%s.%s',
$this->cacheKey,
serialize(func_get_args()),
serialize(request()->query())
);
return Cache::remember($tag, $this->cacheTime...;
}
Another way will be to cache all rows and then paginate them from cache. You will need to make custom collection paginator (google "laravel collection pagination, and will find many tutorials). You may still need to add $with to your cache tag. And for many results isn't a good idea.
Don't try to cache everything. Caching isn't always the fastest way. Better try to optimize your database.
Personally I don't think it is a good idea to cache in repositories.
To flush multiple tags you can use:
Cache::tags('tag1', 'tag2')->flush()
Related
I try to create restful api using Code Igniter 4 on Apache2. If I open http://<my-ip:port>, it shows welcome message. Then I created Account.php controller to get account list from database.
<?php namespace App\Controllers;
use CodeIgniter\RESTful\ResourceController;
use CodeIgniter\API\ResponseTrait;
use App\Models\AccountModel;
class Account extends ResourceController
{
use ResponseTrait;
public function index()
{
$model = new AccountModel();
$data = $model->findAll();
return $this->respond($data, 200);
}
public function show($id = null)
{
$model = new AccountModel();
$data = $model->getWhere(['account_id' => $id])->getResult();
if($data){
return $this->respond($data);
}else{
return $this->failNotFound('No Data Found with id '.$id);
}
}
}
AccountModel.php
<?php namespace App\Models;
use CodeIgniter\Model;
class AccountModel extends Model
{
protected $table = 'account';
protected $primaryKey = 'id';
protected $allowedFields = ['account_id','name'];
}
I set Cors and Filters.
and this is my routes
<?php
namespace Config;
$routes = Services::routes();
if (file_exists(SYSTEMPATH . 'Config/Routes.php')) {
require SYSTEMPATH . 'Config/Routes.php';
}
$routes->setDefaultNamespace('App\Controllers');
$routes->setDefaultController('Home');
$routes->setDefaultMethod('index');
$routes->setTranslateURIDashes(false);
$routes->set404Override();
$routes->setAutoRoute(true);
//$routes->get('/','Home::index');
$routes->resource('account');
if (file_exists(APPPATH . 'Config/' . ENVIRONMENT . '/Routes.php')) {
require APPPATH . 'Config/' . ENVIRONMENT . '/Routes.php';
}
http://my-ip:port shows welcome message. But if I open http://<my-ip:port/account> using postman I got error
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL was not found on this server.</p>
<hr>
<address>Apache/2.4.46 (Ubuntu) Server at <my-ip> Port 80</address>
</body></html>
and I set Account as a default controller $routes->setDefaultController('Account'); I got list of account if I open http://<my-ip:port>. Do I miss some set up? I want to get account list if I open http://<my-ip:port/account> and others.
Is it works if tried http://<my-ip:port/index.php/account? if yes, you have to config your apache to hide index.php from URL.
visit following link for more infos. => more infos
look at my code best way using restful ctl ci4
first routs
<?php
/*
* Core Auth routes file.
*/
$routes->group('api', ['namespace' => 'Modules\Auth\Controllers'], function ($routes) {
$routes->resource('group', ['filter' => 'authJwt']);
$routes->resource('permission', ['filter' => 'authJwt']);
$routes->resource('groupPermission', ['filter' => 'authJwt']);
$routes->resource('userPermission', ['filter' => 'authJwt']);
$routes->group('auth', function ($routes) {
$routes->post('signin-jwt', 'Auth::signInJwt', ['filter' => 'isSignIn']);
$routes->post('signin', 'Auth::signIn', ['filter' => 'isSignIn']);
$routes->get('signout', 'Auth::signOut', ['filter' => 'authJwt']);
$routes->get('is-signin', 'Auth::isSignIn',['filter' => 'authJwt']);
$routes->post('signup', 'Auth::signUp', ['filter' => 'isSignIn']);
$routes->post('forgot', 'Auth::forgot', ['filter' => 'isSignIn']);
$routes->post('reset-password-email', 'Auth::resetPasswordViaEmail', ['filter' => 'isSignIn']);
$routes->post('reset-password-sms', 'Auth::resetPasswordViaSms', ['filter' => 'isSignIn']);
$routes->post('activate-account-email', 'Auth::activateAccountViaEmail', ['filter' => 'isSignIn']);
$routes->post('send-activate-email', 'Auth::sendActivateCodeViaEmail', ['filter' => 'isSignIn']);
$routes->post('activate-account-sms', 'Auth::activateAccountViaSms', ['filter' => 'isSignIn']);
$routes->post('send-activate-sms', 'Auth::sendActivateCodeViaSms', ['filter' => 'isSignIn']);
});
});
sencond api ctl
<?php
namespace Modules\Shared\Controllers;
/**
* Class BaseController
*
* BaseController provides a convenient place for loading components
* and performing functions that are needed by all your controllers.
* Extend this class in any new controllers:
* class Home extends BaseController
*
* For security be sure to declare any new methods as protected or private.
*
* #package CodeIgniter
*/
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\RESTful\ResourceController;
use Modules\Auth\Config\Services;
use Myth\Auth\AuthTrait;
use Psr\Log\LoggerInterface;
use Modules\Shared\Interfaces\UrlAggregationInterface;
use Modules\Shared\Libraries\UrlAggregation;
class ApiController extends ResourceController
{
use AuthTrait;
protected $format = "";
public object $userObject;
public UrlAggregationInterface $urlAggregation;
/**
* An array of helpers to be loaded automatically upon
* class instantiation. These helpers will be available
* to all other controllers that extend BaseController.
*
* #var array
*/
protected $helpers = [
'cookie',
'url',
'from',
'filesystem',
'text',
'shared'
];
/**
* Constructor.
*
* #param RequestInterface $request
* #param ResponseInterface $response
* #param LoggerInterface $logger
*/
/**
* #var string
* Holds the session instance
*/
protected $session;
public function __construct()
{
$this->userObject = (object)[];
}
public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger)
{
// Do Not Edit This Line
parent::initController($request, $response, $logger);
$this->urlAggregation = new UrlAggregation($request);
$requestWithUser = Services::requestWithUser();
$this->userObject = $requestWithUser->getUser();
}
}
thrid ctl
<?php namespace Modules\Auth\Controllers;
use Modules\Auth\Config\Services;
use Modules\Auth\Entities\GroupEntity;
use CodeIgniter\HTTP\ResponseInterface;
use Modules\Shared\Controllers\ApiController;
class Group extends ApiController
{
/**
* index function
* #method : GET
*/
public function index()
{
$groupEntity = new GroupEntity();
$this->urlAggregation->dataMap($groupEntity->getDataMap());
$groupService = Services::groupService();
$findAllData = $groupService->index($this->urlAggregation);
return $this->respond([
'data' => $findAllData['data'],
'pager' => $findAllData['pager']
], ResponseInterface::HTTP_OK, lang('Shared.api.receive'));
}
/**
* show function
* #method : GET with params ID
*/
public function show($id = null)
{
$groupService = Services::groupService();
$findOneData = $groupService->show($id);
return $this->respond([
'data' => $findOneData['data'],
'pager' => $findOneData['pager']
], ResponseInterface::HTTP_OK, lang('Shared.api.receive'));
}
public function create()
{
$rules = [
'name' => 'required|min_length[3]|max_length[255]|is_unique[auth_groups.name]',
'description' => 'required|min_length[3]|max_length[255]',
];
if (!$this->validate($rules)) {
return $this->respond([
'error' => $this->validator->getErrors(),
], ResponseInterface::HTTP_NOT_ACCEPTABLE, lang('Shared.api.validation'));
}
$groupEntity = new GroupEntity((array)$this->request->getVar());
$groupService = Services::groupService();
$groupService->create($groupEntity);
return $this->respond([
'data' => ''
], ResponseInterface::HTTP_CREATED, lang('Shared.api.save'));
}
/**
* update function
* #method : PUT or PATCH
*/
public function update($id = null)
{
//get request from Vue Js
//get request from Vue Js
$json = $this->request->getJSON();
if (!isset($id)) {
$id = $json->id;
}
$rules = [
'name' => 'if_exist|required|min_length[3]|max_length[255]',
'description' => 'required|min_length[3]|max_length[255]',
];
if (!$this->validate($rules)) {
return $this->respond([
'error' => $this->validator->getErrors(),
], ResponseInterface::HTTP_NOT_ACCEPTABLE, lang('Shared.api.validation'));
}
$groupEntity = new GroupEntity((array)$this->request->getVar());
$groupService = Services::groupService();
$groupService->update($id, $groupEntity);
return $this->respond([
], ResponseInterface::HTTP_OK, lang('Shared.api.update'));
}
/**
* edit function
* #method : DELETE with params ID
*/
public function delete($id = null)
{
$groupService = Services::groupService();
$groupService->delete($id);
return $this->respond([
], ResponseInterface::HTTP_OK, lang('Shared.api.remove'));
}
}
entitiy
forth service
<?php namespace Modules\Auth\Config;
use CodeIgniter\HTTP\UserAgent;
use Config\App;
use Config\Services as AppServices;
use Config\Services as BaseService;
use Modules\Auth\Libraries\RequestWithUser;
use Modules\Auth\Services\AuthService;
use Modules\Auth\Services\GroupsPermissionService;
use Modules\Auth\Services\PermissionService;
use Modules\Auth\Services\RoleRouteService;
use Modules\Auth\Services\GroupService;
use Modules\Auth\Services\UsersPermissionService;
class Services extends BaseService
{
//--------------------------------------------------------------------
/**
* The Request class models an HTTP request.
*
* #param App|null $config
* #param boolean $getShared
*
* #return RequestWithUser
*/
public static function requestWithUser(App $config = null, bool $getShared = true)
{
if ($getShared) {
return static::getSharedInstance('requestWithUser', $config);
}
$config = $config ?? config('App');;
return new RequestWithUser(
$config,
AppServices::uri(),
'php://input',
new UserAgent()
);
}
//--------------------------------------------------------------------
public static function roleRoute($getShared = true)
{
if ($getShared) {
return static::getSharedInstance('roleRoute');
}
return new RoleRouteService();
}
//--------------------------------------------------------------------
public static function authService($getShared = false)
{
if (!$getShared) {
return new AuthService();
}
return static::getSharedInstance('authService');
}
//--------------------------------------------------------------------
public static function groupService($getShared = false)
{
if (!$getShared) {
return new GroupService();
}
return static::getSharedInstance('groupService');
}
//--------------------------------------------------------------------
public static function permissionService($getShared = false)
{
if (!$getShared) {
return new PermissionService();
}
return static::getSharedInstance('permissionService');
}
//--------------------------------------------------------------------
public static function groupsPermissionService($getShared = false)
{
if (!$getShared) {
return new GroupsPermissionService();
}
return static::getSharedInstance('groupsPermissionService');
}
//--------------------------------------------------------------------
public static function userPermissionService($getShared = false)
{
if (!$getShared) {
return new UsersPermissionService();
}
return static::getSharedInstance('usersPermissionService');
}
//--------------------------------------------------------------------
}
<?php namespace Modules\Auth\Entities;
use \CodeIgniter\Entity;
use CodeIgniter\I18n\Time;
class GroupEntity extends Entity
{
protected $id;
protected $name;
protected $description;
//check type of data
// protected $casts = ['
// is_flag' => 'boolean'];
protected $attributes = [
'id' => null,
'name' => null,
'description' => null,
];
protected $datamap = [
];
protected $dates = [];
protected $casts = [];
protected $permissions = [];
protected $roles = [];
}
model
<?php namespace Myth\Auth\Authorization;
use CodeIgniter\Model;
use Modules\Auth\Entities\GroupEntity;
use Modules\Shared\Models\Aggregation;
class GroupModel extends Aggregation
{
protected $table = 'auth_groups';
protected $primaryKey = 'id';
protected $returnType = GroupEntity::class;
protected $allowedFields = [
'name', 'description'
];
protected $useTimestamps = false;
protected $validationRules = [
'name' => 'required|max_length[255]|is_unique[auth_groups.name,name,{name}]',
'description' => 'max_length[255]',
];
protected $validationMessages = [];
protected $skipValidation = false;
//--------------------------------------------------------------------
// Users
//--------------------------------------------------------------------
/**
* Adds a single user to a single group.
*
* #param int $userId
* #param int $groupId
*
* #return bool
*/
public function addUserToGroup(int $userId, int $groupId)
{
cache()->delete("{$groupId}_users");
cache()->delete("{$userId}_groups");
cache()->delete("{$userId}_permissions");
$data = [
'user_id' => (int) $userId,
'group_id' => (int) $groupId
];
return (bool) $this->db->table('auth_groups_users')->insert($data);
}
/**
* Removes a single user from a single group.
*
* #param int $userId
* #param int|string $groupId
*
* #return bool
*/
public function removeUserFromGroup(int $userId, $groupId)
{
cache()->delete("{$groupId}_users");
cache()->delete("{$userId}_groups");
cache()->delete("{$userId}_permissions");
return $this->db->table('auth_groups_users')
->where([
'user_id' => $userId,
'group_id' => (int) $groupId
])->delete();
}
/**
* Removes a single user from all groups.
*
* #param int $userId
*
* #return bool
*/
public function removeUserFromAllGroups(int $userId)
{
cache()->delete("{$userId}_groups");
cache()->delete("{$userId}_permissions");
return $this->db->table('auth_groups_users')
->where('user_id', (int)$userId)
->delete();
}
/**
* Returns an array of all groups that a user is a member of.
*
* #param int $userId
*
* #return array
*/
public function getGroupsForUser(int $userId)
{
if (null === $found = cache("{$userId}_groups"))
{
$found = $this->builder()
->select('auth_groups_users.*, auth_groups.name, auth_groups.description')
->join('auth_groups_users', 'auth_groups_users.group_id = auth_groups.id', 'left')
->where('user_id', $userId)
->get()->getResultArray();
cache()->save("{$userId}_groups", $found, 300);
}
return $found;
}
/**
* Returns an array of all users that are members of a group.
*
* #param int $groupId
*
* #return array
*/
public function getUsersForGroup(int $groupId)
{
if (null === $found = cache("{$groupId}_users"))
{
$found = $this->builder()
->select('auth_groups_users.*, users.*')
->join('auth_groups_users', 'auth_groups_users.group_id = auth_groups.id', 'left')
->join('users', 'auth_groups_users.user_id = users.id', 'left')
->where('auth_groups.id', $groupId)
->get()->getResultArray();
cache()->save("{$groupId}_users", $found, 300);
}
return $found;
}
//--------------------------------------------------------------------
// Permissions
//--------------------------------------------------------------------
/**
* Gets all permissions for a group in a way that can be
* easily used to check against:
*
* [
* id => name,
* id => name
* ]
*
* #param int $groupId
*
* #return array
*/
public function getPermissionsForGroup(int $groupId): array
{
$permissionModel = model(PermissionModel::class);
$fromGroup = $permissionModel
->select('auth_permissions.*')
->join('auth_groups_permissions', 'auth_groups_permissions.permission_id = auth_permissions.id', 'inner')
->where('group_id', $groupId)
->findAll();
$found = [];
foreach ($fromGroup as $permission)
{
$found[$permission['id']] = $permission;
}
return $found;
}
/**
* Add a single permission to a single group, by IDs.
*
* #param int $permissionId
* #param int $groupId
*
* #return mixed
*/
public function addPermissionToGroup(int $permissionId, int $groupId)
{
$data = [
'permission_id' => (int)$permissionId,
'group_id' => (int)$groupId
];
return $this->db->table('auth_groups_permissions')->insert($data);
}
//--------------------------------------------------------------------
/**
* Removes a single permission from a single group.
*
* #param int $permissionId
* #param int $groupId
*
* #return mixed
*/
public function removePermissionFromGroup(int $permissionId, int $groupId)
{
return $this->db->table('auth_groups_permissions')
->where([
'permission_id' => $permissionId,
'group_id' => $groupId
])->delete();
}
//--------------------------------------------------------------------
/**
* Removes a single permission from all groups.
*
* #param int $permissionId
*
* #return mixed
*/
public function removePermissionFromAllGroups(int $permissionId)
{
return $this->db->table('auth_groups_permissions')
->where('permission_id', $permissionId)
->delete();
}
}
I have the following routes in web.php, the first five routes are working perfectly but from contacts to aboutroutes` fail with the following exception:
Illuminate\Contracts\Encryption\DecryptException The payload is invalid.
Route::get('services', 'PageController#services')->name('services');
Route::get('/service/{id}', 'PageController#showService')->name('service');
Route::get('/blogs', 'PageController#showBlogs')->name('blogs');
Route::get('/{blog}', 'PageController#showPost')->name('post.show');
Route::post('/comment/{blog}/store', 'PageController#storeComment')->name('comment.store');
Route::get('/contacts', 'PageController#contacts')->name('contacts');
Route::post('/contact/store', 'PageController#storeContact')->name('contact.store');
Route::get('/courses', 'PageController#showCourses')->name('courses');
Route::get('/{course}', 'PageController#categoryCourses')->name('course.category');
Route::get('coursesdetail', 'PageController#showCoursesDetail')->name('coursesdetail');
Route::get('resource', 'PageController#showResource')->name('resource');
Route::get('about', 'PageController#showAbout')->name('about');
PageController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Crypt;
use App\About;
use App\Team;
use App\Service;
use App\Post;
use App\Category;
use App\Tag;
use App\Slider;
use App\Contact;
use App\Client;
use App\Comment;
use App\Course;
use App\Coursecategory;
class PageController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
$about = About::all();
$teams = Team::all();
$services = Service::all();
$posts = Post::orderBy('created_at', 'desc')->take(3)->get();
$sliders = Slider::all();
$clients = Client::all();
return view('index')->with('about', $about)
->with('teams', $teams)
->with('services', $services)
->with('posts', $posts)
->with('sliders', $sliders)
->with('clients', $clients);
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param int $id
* #return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function destroy($id)
{
//
}
public function services()
{
$services = Service::all();
return view('service')->with('services', $services);
}
public function showService($id)
{
$id = Crypt::decrypt($id);
$service = Service::find($id);
$services = Service::all();
return view('service')->with('service', $service)->with('services', $services);
}
public function showBlogs()
{
// $posts = Post::orderBy('created_at', 'desc')->take(5)->get();
// $recents = Post::orderBy('created_at', 'desc')->take(5)->get();
$posts = Post::orderBy('created_at', 'desc')->paginate(4);
$recents = Post::orderBy('created_at', 'desc')->take(4)->get();
// $posts = Post::all();
$tags = Tag::all();
$categories = Category::all();
return view('blogs')->with('tags', $tags)
->with('categories', $categories)
->with('posts', $posts)
->with('recents', $recents);
}
public function showPost(Request $request, $id)
{
$id = Crypt::decrypt($id);
$posts = [Post::find($id)];
$recents = Post::orderBy('created_at', 'desc')->take(4)->get();
$tags = Tag::all();
$categories = Category::all();
// $next_id = Post::where('id', '>', $id)->min('id');
// $prev_id = Post::where('id', '<', $id)->max('id');
// dd($posts);
return view('post')->with('posts', $posts)
->with('recents', $recents)
->with('tags', $tags)
->with('categories', $categories);
// ->with('next', Post::find($next_id))
// ->with('prev', Post::find($prev_id));
}
public function storeComment(Request $request, $post)
{
request()->validate([
'name' => 'required',
'email' => 'required|email',
'phone' => 'required',
]);
$contact = Comment::create([
'post_id' => $post,
'user_id' => Auth::id(),
'name' => $request->name,
'email' => $request->email,
'phone' => $request->phone,
'comment' => $request->comments,
]);
session()->flash('success', 'Comment successfully submitted');
return redirect()->back();
}
public function contacts()
{
return view('contact');
}
public function storeContact(Request $request)
{
request()->validate([
'name' => 'required',
'email' => 'required|email',
'phone' => 'required',
]);
$contact = Contact::create([
'name' => $request->name,
'email' => $request->email,
'phone' => $request->phone,
'comment' => $request->comments,
]);
session()->flash('success', 'Contact information successfully submitted');
return redirect()->route('contact');
}
public function showCourses()
{
$categories = Coursecategory::all();
$courses = Course::orderBy('created_at', 'desc')->paginate(4);
return view('courses')->with('courses', $courses)
->with('categories', $categories);
}
public function categoryCourses($id)
{
$id = Crypt::decrypt($id);
$course = Coursecategory::where('id', $id)->first()->courses;
$categories = Coursecategory::all();
return view('coursewithcategory')->with('course', $course)
->with('categories', $categories);
}
public function showCoursesDetail()
{
return view('coursesdetail');
}
public function showResource()
{
return view('resource');
}
public function showAbout()
{
$about = About::all();
return view('about')->with('about', $about);
}
}
This should be the order your routes when you use uri as slug.
Route::get('/contacts', 'PageController#contacts')->name('contacts');
Route::post('/contact/store', 'PageController#storeContact')->name('contact.store');
Route::get('/courses', 'PageController#showCourses')->name('courses');
Route::get('coursesdetail', 'PageController#showCoursesDetail')->name('coursesdetail');
Route::get('resource', 'PageController#showResource')->name('resource');
Route::get('about', 'PageController#showAbout')->name('about');
Route::get('/{course}', 'PageController#categoryCourses')->name('course.category');
I want to make an instance of my model in my controller and use it every where i need
I use this code:
public $test = new Access();
but the is this error that i cant figure it out why i kept getting this error:
expression is not allowed as field default value
and this is my controller code down here:
<?php
namespace App\Http\Controllers;
use App\Models\Access;
use Illuminate\Http\Request;
classAccessController extends Controller{
private $table = 'accesses';
public $test = new Access();
/**
* #return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function index()
{
$table = $this->table;
$accesses = (new Access())->index($table);
return view('index', compact('accesses'));
}
/**
* #param Request $request
* #return \Illuminate\Http\RedirectResponse
*/
public function store(Request $request)
{
$access = new Access();
$request->validate([
'can_select' => 'required|boolean',
'can_delete' => 'required|boolean',
'can_edit' => 'required|boolean',
'can_insert' => 'required|boolean',
'role_id' => 'required|integer|max:2',
'module_id' => 'required|integer|max:3',
]);
$access->can_select = $request->get('can_select');
$access->can_delete = $request->get('can_delete');
$access->can_edit = $request->get('can_edit');
$access->can_insert = $request->get('can_insert');
$access->role_id = $request->get('role_id');
$access->module_id = $request->get('module_id');
$attributes = array('can_select', 'can_delete', 'can_edit', 'can_insert', 'role_id', 'module_id');
$options = array($access->can_select, $access->can_delete, $access->can_edit, $access->can_insert, $access->role_id, $access->module_id);
$table = $this->table;
(new Access())->store($table, $attributes, $options);
return redirect('accesses')->with('success', 'Information has been inserted');
}
/**
* #param $id
* #return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function edit($id)
{
$access = Access::find($id);
return view('update', compact('access', 'id'));
}
/**
* #param Request $request
* #param $id
* #return \Illuminate\Http\RedirectResponse
*/
public function update(Request $request, $id)
{
$access = Access::find($id);
$request->validate([
'can_select' => 'required|boolean',
'can_delete' => 'required|boolean',
'can_edit' => 'required|boolean',
'can_insert' => 'required|boolean',
'role_id' => 'required|integer|max:2',
'module_id' => 'required|integer|max:3',
]);
$access->can_select = $request->get('can_select');
$access->can_delete = $request->get('can_delete');
$access->can_edit = $request->get('can_edit');
$access->can_insert = $request->get('can_insert');
$access->role_id = $request->get('role_id');
$access->module_id = $request->get('module_id');
$attributes = array('can_select', 'can_delete', 'can_edit', 'can_insert', 'role_id', 'module_id');
$options = array($access->can_select, $access->can_delete, $access->can_edit, $access->can_insert, $access->role_id, $access->module_id);
$object = $access;
$table = $this->table;
(new Access())->updates($table, $object, $attributes, $options);
return redirect('accesses')->with('success', 'Information has been updated successfully!!');
}
/**
* #param $id
* #return \Illuminate\Http\RedirectResponse
*/
public function destroy($id)
{
$access = Access::find($id);
$object = $access;
$table = $this->table;
(new Access())->erase($table, $object);
return redirect('accesses')->with('success', 'Information has been deleted');
}
}
i first thought it is the security problem but in my idea it is irrelevent in my idea
I don't understand your use case but.. you can use the contructor of the class to do so:
class ACoolController extends Controller {
protected $access;
/**
* ACoolController constructor.
*
*/
public function __construct()
{
$this->access = new Access();
}
public function aCoolFunction()
{
// do something with your variable
$this->access->someMethodOfYourModel();
}
}
Of-course you can't in PHP you cannot call a method to instantiate a class member even if it is a static method either initialize it in the constructor
class AccessController extends Controller{
public $test ;
public function __construct()
{
$this->test= new Access();
}
}
Or much better use the dependency injection pattern ( Container ) in Laravel to avoid creating multiple instances of the Access Model see the docs : https://laravel.com/docs/5.7/container
Suppose I have a query that returns the following data:
RangeId | MinValue | MaxValue | Resolution | UnitId | UnitName
I want to hydrate the object MeasurementRange with the above data.
class MeasurementRange {
public function getRangeId() {...};
public function setRangeId($id) {...};
public function getRange() {...};
public function setRange(Range $range) {...};
public function getUnit() {...};
public function setUnit(Unit $unit) {...};
}
class Range {
public function getMinValue() {...};
public function setMinValue(float $minVal) {...};
public function getMaxValue() {...};
public function setMaxValue(float $maxVal) {...};
public function getResolution {...};
public function setResolution(float $resolution) {...};
}
class Unit {
public function getUnitId() {...};
public function setUnitId(int $id) {...};
public function getUnitName() {...};
public function setUnitName(string $name) {...};
}
As you can see the MeasurementRange object has set Range and Unit objects.
How can I hydrate MeasurementRange and the inner Range and Unit objects from the above query?
PS: I didn't specify protected properties of the objects. I guess they are self-evident.
You need to create a mapper, that will use your dbAdapter to fetch the data as an array, and then use hydrators to hydrate all the objects, and finally add the Range and Unit to MeasurementRange. You could alternatively create a custom hydrator (that would be even better, in terms of single responsibility).
I haven't got time to clean the example below, but that's what it could look like :)
final class LanguageMapper
{
/**
* #param LanguageTable $languageTable
* #param PackageTable $packageTable
* #param Cache $cache
* #param LoggerInterface $logger
*/
public function __construct(LanguageTable $languageTable, PackageTable $packageTable, Cache $cache, LoggerInterface $logger)
{
$this->languageTable = $languageTable;
$this->packageTable = $packageTable;
$this->cache = $cache;
$this->logger = $logger;
}
/**
* #param array $where
*
* #return array List of active languages
*/
public function findActive(array $where = [])
{
try {
if (empty($where) && $this->cache->hasItem('active_languages')) {
return unserialize($this->cache->getItem('active_languages'));
}
} catch (RuntimeException $exception) {
$this->logger->critical($exception->getMessage(), [
'exception' => $exception,
'file' => $exception->getFile(),
'line' => $exception->getLine(),
]);
}
/* #var $adapter \Zend\Db\Adapter\Adapter */
$adapter = $this->languageTable->getGateway()->getAdapter();
$sql = new Sql($adapter);
$select = $sql->select()->columns([Select::SQL_STAR])
->from('language')
->join('package', 'package.id = language.package', Select::SQL_STAR, Select::JOIN_LEFT)
->where(array_merge($where, ['active' => true]))
->order(['position']);
$selectString = $sql->buildSqlString($select);
$resultSet = $adapter->query($selectString, Adapter::QUERY_MODE_EXECUTE);
$languages = [];
$hydrator = new ArraySerializable();
foreach ($resultSet as $result) {
$language = new Language();
$package = new Package();
$hydrator->hydrate((array) $result, $package);
$hydrator->hydrate((array) $result, $language);
$language->setPackage($package);
$languages[] = $language;
}
if (empty($where)) {
try {
$this->cache->setItem('active_languages', serialize($languages));
} catch (RuntimeException $exception) {
$this->logger->warning($exception->getMessage(), [
'exception' => $exception,
'file' => $exception->getFile(),
'line' => $exception->getLine(),
]);
}
}
return $languages;
}
}
I have a site I created that has a blog section and a video section. I had a config file for blog that I tried to share with the video section but it wasn't working properly so I created a separate config for video. and modified my column names for video from
$title and $subtitle
to
$v_title and $v_subtitle.
but when I do I get the following error
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '' for key 'videos_slug_unique'
for some reason a slug is not being produced and this causes the issue. The slug is unique in my table. If I change the variables to how they were
$title and $subtitle
it works, why is that?
this is my Admin videoController
<?php
namespace App\Http\Controllers\Admin;
use App\Jobs\VideoFormFields;
use App\Http\Requests;
use App\Http\Requests\VideoCreateRequest;
use App\Http\Requests\VideoUpdateRequest;
use App\Http\Controllers\Controller;
use App\Video;
class VideoController extends Controller
{
/**
* Display a listing of the posts.
*/
public function index()
{
return view('admin.video.index')
->withVideos(Video::all());
}
/**
* Show the new video form
*/
public function create()
{
$data = $this->dispatch(new VideoFormFields());
return view('admin.video.create', $data);
}
/**
* Store a newly created Video
*
* #param VideoCreateRequest $request
*/
public function store(VideoCreateRequest $request)
{
$video = Video::create($request->videoFillData());
$video->syncTags($request->get('tags', []));
return redirect()
->route('admin.video.index')
->withSuccess('New Video Successfully Created.');
}
/**
* Show the video edit form
*
* #param int $id
* #return Response
*/
public function edit($id)
{
$data = $this->dispatch(new VideoFormFields($id));
return view('admin.video.edit', $data);
}
/**
* Update the Video
*
* #param VideoUpdateRequest $request
* #param int $id
*/
public function update(VideoUpdateRequest $request, $id)
{
$video = Video::findOrFail($id);
$video->fill($request->videoFillData());
$video->save();
$video->syncTags($request->get('tags', []));
if ($request->action === 'continue') {
return redirect()
->back()
->withSuccess('Video saved.');
}
return redirect()
->route('admin.video.index')
->withSuccess('Video saved.');
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return Response
*/
public function destroy($id)
{
$video = Video::findOrFail($id);
$video->tags()->detach();
$video->delete();
return redirect()
->route('admin.video.index')
->withSuccess('Video deleted.');
}
}
this is my videoFormFields
<?php
namespace App\Jobs;
use App\Video;
use App\Tag;
use Carbon\Carbon;
use Illuminate\Contracts\Bus\SelfHandling;
class VideoFormFields extends Job implements SelfHandling
{
/**
* The id (if any) of the Post row
*
* #var integer
*/
protected $id;
/**
* List of fields and default value for each field
*
* #var array
*/
protected $fieldList = [
'v_title' => '',
'v_subtitle' => '',
'page_image' => '',
'content' => '',
'meta_description' => '',
'is_draft' => "0",
'publish_date' => '',
'publish_time' => '',
'layout' => 'video.layouts.v_post',
'tags' => [],
];
/**
* Create a new command instance.
*
* #param integer $id
*/
public function __construct($id = null)
{
$this->id = $id;
}
/**
* Execute the command.
*
* #return array of fieldnames => values
*/
public function handle()
{
$fields = $this->fieldList;
if ($this->id) {
$fields = $this->fieldsFromModel($this->id, $fields);
} else {
$when = Carbon::now()->addHour();
$fields['publish_date'] = $when->format('M-j-Y');
$fields['publish_time'] = $when->format('g:i A');
}
foreach ($fields as $fieldName => $fieldValue) {
$fields[$fieldName] = old($fieldName, $fieldValue);
}
return array_merge(
$fields,
['allTags' => Tag::lists('tag')->all()]
);
}
/**
* Return the field values from the model
*
* #param integer $id
* #param array $fields
* #return array
*/
protected function fieldsFromModel($id, array $fields)
{
$video = Video::findOrFail($id);
$fieldNames = array_keys(array_except($fields, ['tags']));
$fields = ['id' => $id];
foreach ($fieldNames as $field) {
$fields[$field] = $video->{$field};
}
$fields['tags'] = $video->tags()->lists('tag')->all();
return $fields;
}
}
this is my videoCreateRequest
<?php
namespace App\Http\Requests;
use Carbon\Carbon;
class VideoCreateRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'v_title' => 'required',
'v_subtitle' => 'required',
'content_raw' => 'required', // HERE CHANGED
'publish_date' => 'required',
'publish_time' => 'required',
'layout' => 'required',
];
}
/**
* Return the fields and values to create a new VIDEO post from
*/
public function videoFillData()
{
$published_at = new Carbon(
$this->publish_date.' '.$this->publish_time
);
return [
'v_title' => $this->v_title,
'v_subtitle' => $this->v_subtitle,
'page_image' => $this->page_image,
'content_raw' => $this->content_raw, // HERE CHANGED
'meta_description' => $this->meta_description,
'is_draft' => (bool)$this->is_draft,
'published_at' => $published_at,
'layout' => $this->layout,
];
}
}
this is my videoUpdateRequest
class VideoUpdateRequest extends VideoCreateRequest
{
//
}
this is my video model
<?php
namespace App;
use App\Services\Markdowner;
use Illuminate\Database\Eloquent\Model;
use Carbon\Carbon;
use Sofa\Eloquence\Eloquence;
class Video extends Model
{
use Eloquence;
protected $dates = ['published_at'];
protected $fillable = [
'v_title', 'v_subtitle', 'content_raw', 'page_image', 'meta_description',
'layout', 'is_draft', 'published_at',
];
/**
* The many-to-many relationship between posts and tags.
*
* #return BelongsToMany
*/
public function tags()
{
return $this->morphToMany('App\Tag', 'taggable');
}
/**
* Set the title attribute and automatically the slug
*
* #param string $value
*/
public function setTitleAttribute($value)
{
$this->attributes['title'] = $value;
if (! $this->exists) {
$this->setUniqueSlug($value, '');
}
}
/**
* Recursive routine to set a unique slug
*
* #param string $title
* #param mixed $extra
*/
protected function setUniqueSlug($title, $extra)
{
$slug = str_slug($title.'-'.$extra);
if (static::whereSlug($slug)->exists()) {
$this->setUniqueSlug($title, $extra + 1);
return;
}
$this->attributes['slug'] = $slug;
}
/**
* Set the HTML content automatically when the raw content is set
*
* #param string $value
*/
public function setContentRawAttribute($value)
{
$markdown = new Markdowner();
$this->attributes['content_raw'] = $value;
$this->attributes['content_html'] = $markdown->toHTML($value);
}
/**
* Sync tag relation adding new tags as needed
*
* #param array $tags
*/
public function syncTags(array $tags)
{
Tag::addNeededTags($tags);
if (count($tags)) {
$this->tags()->sync(
Tag::whereIn('tag', $tags)->lists('id')->all()
);
return;
}
$this->tags()->detach();
}
/**
* Return the date portion of published_at
*/
public function getPublishDateAttribute($value)
{
return $this->published_at->format('M-j-Y');
}
/**
* Return the time portion of published_at
*/
public function getPublishTimeAttribute($value)
{
return $this->published_at->format('g:i A');
}
/**
* Alias for content_raw
*/
public function getContentAttribute($value)
{
return $this->content_raw;
}
/**
* Return URL to post
*
* #param Tag $tag
* #return string
*/
public function url(Tag $tag = null)
{
$url = url('video/'.$this->slug); // this fixed my problem it was 'blog/'
if ($tag) {
$url .= '?tag='.urlencode($tag->tag);
}
return $url;
}
/**
* Return array of tag links
*
* #param string $base
* #return array
*/
public function tagLinks($base = '/video?tag=%TAG%') // this fixed my problem it was 'blog?tag=%TAG%/'
{
$tags = $this->tags()->lists('tag');
$return = [];
foreach ($tags as $tag) {
$url = str_replace('%TAG%', urlencode($tag), $base);
$return[] = ''.e($tag).'';
}
return $return;
}
/**
* Return next post after this one or null
*
* #param Tag $tag
* #return Post
*/
public function newerPost(Tag $tag = null) // //here newVideo v_index & v_post
{
$query =
static::where('published_at', '>', $this->published_at)
->where('published_at', '<=', Carbon::now())
->where('is_draft', 0)
->orderBy('published_at', 'asc');
if ($tag) {
$query = $query->whereHas('tags', function ($q) use ($tag) {
$q->where('tag', '=', $tag->tag);
});
}
return $query->first();
}
/**
* Return older post before this one or null
*
* #param Tag $tag
* #return Post
*/
public function olderPost(Tag $tag = null) // //here olderVideo v_index & v_post
{
$query =
static::where('published_at', '<', $this->published_at)
->where('is_draft', 0)
->orderBy('published_at', 'desc');
if ($tag) {
$query = $query->whereHas('tags', function ($q) use ($tag) {
$q->where('tag', '=', $tag->tag);
});
}
return $query->first();
}
}
this is my video table
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateVideosTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('videos', function (Blueprint $table) {
$table->increments('id');
$table->string('slug')->unique();
$table->string('v_title');
$table->string('v_subtitle');
$table->text('content_raw');
$table->text('content_html');
$table->string('page_image');
$table->string('meta_description');
$table->boolean('is_draft');
$table->string('layout')
->default('blog.layouts.post');
$table->timestamps();
$table->timestamp('published_at')->index();
});
}
/**
* Reverse the migrations.
*/
public function down()
{
Schema::drop('videos');
}
}
After you changed the column names, your dynamic setters setTitleAttribute and setSubtitleAttribute are not called and the slug does not get updated. You need to change the names of setter methods as well.
public function setVTitleAttribute($value) {
...
}
public function setVSubtitleAttribute($value) {
...
}
it seems you did not refactor title to v_title in the whole class. For example, you should change
public function setTitleAttribute($value)
{
$this->attributes['title'] = $value;
if (! $this->exists) {
$this->setUniqueSlug($value, '');
}
}
to
public function setVTitleAttribute($value)
{
$this->attributes['v_title'] = $value;
if (! $this->exists) {
$this->setUniqueSlug($value, '');
}
}