How to denote a Request Facade by a variable in Laravel? - laravel-6

I am doing some experiment to make my controllers as much dynamic as I can. Let me give you a brief overview. I have a controller Logo Controller which I have set up like this:
use App\Models\Logo;
class LogoController extends Controller
{
public function add(Request $request)
{
$data['entity'] = 'logo';
$newEntityObj = new Logo;
$newEntityObj->title = $title; // set title
$newEntityObj->type = $type; // set type
$saveNewEntityData = $newEntityObj->save(); // save the entity data
------------------
-------------------
}
}
Now I made some changes like:
using a variable to denote the Logo Model.
$modelClass = "App\\Models\\" . ucfirst($data['entity']);
And then, using the $modelClass variable to execution Eloquent actions on it, like this:-
$newEntityObj = new $modelClass;
$newEntityObj->title = $title; // set title
$newEntityObj->type = $type; // set type
$saveNewEntityData = $newEntityObj->save(); // save the entity data
So the Logo Controller Class has been updated to:
use App\Models\Logo;
class LogoController extends Controller
{
public function add(Request $request)
{
$data['entity'] = 'logo';
$modelClass = "App\\Models\\" . ucfirst($data['entity']);
$newEntityObj = new $modelClass;
$newEntityObj->title = $title; // set title
$newEntityObj->type = $type; // set type
$saveNewEntityData = $newEntityObj->save(); // save the entity data
------------------
-------------------
}
}
Now I have created a Validationb Request File to use it for form validation. I am using it like this:
// Request Validation Inclusion //
use App\Http\Requests\AdminRequests\LogoValidation\LogoRequest;
public function add(LogoRequest $request)
{
--------------------------
--------------------------
}
Now instead of writing public function add(LogoRequest $request) I want to make it more dynamic. Something like this:
class LogoController extends Controller
{
public static $classEntity = 'logo';
public static $classFormattedEntity = null;
public static $classRequestVariable = null;
public function __construct()
{
$entityArray = explode('-', str_replace('_', '-', self::$classEntity));
foreach($entityArray as $keyEntity => $rowEntity)
{
if($keyEntity !== 0)
$entityArray[$keyEntity] = ucfirst($rowEntity);
}
self::$classFormattedEntity = implode('', $entityArray);
self::$classRequestVariable = "App\\Http\\Requests\\AdminRequests\\" . ucfirst(self::$classFormattedEntity) . "Validation\\" . ucfirst(self::$classFormattedEntity) . "Request";
}
public function add(self::$classRequestVariable $request)
{
..............................
..............................
}
}
The variable self::$classRequestVariable actually prints App\Http\Requests\AdminRequests\LogoValidation\LogoRequest
But when I am writing public function add(self::$classRequestVariable $request) instead of public function add(LogoRequest $request) I am getting the following error:

Related

Create correct object relation

I'm starting to learn OOP and I know it's hard to build good, quality, testable code and I'm afraid to make some architectural mistake and the beginning because it's harder to refactor later.
Currently, I'm working on Laravel and I need a component (a small part of a program) to calculate online advertising statistics (CPM, EPC and so on) uisng cronjob. For this purpose, I need to collect data from the database, calculate statistic(s) and store it to related table. This need to be run through CLI using cronjob. Calculation of stats should be done if possible by SQL, but it not always can be done with current architecture.
So I need to create some reusable component which can be easily extended with new stat calculation logic, either with just fetch already calculated logic from DB and store it or fetch, calculate and store to DB. And to have ability for futuhre to use it easily in any part of application not just by CLI.
To run it from CLI I'm using Laravel command with scheduling:
class StatsComamnd extends Command
{
protected $signature = 'project:calculatestats {statName}';
public function __construct(StatsService $statsService){
parent::__construct();
$this->statsService = $statsService;
}
public function handle() {
$method = $this->argument('statName');
if(!method_exists($this, $method)) {
$this->error('Invalid stat name provided!');
}
$this->{$method}();
}
public function networkOffers():void {
$this->stastService->setStatsHandler(app(OffersNetworkStatsHandler::class))->handle();
}
public function networkOffersCpm():void{
app(OffersNetworkCpmHandler::class)->handle();
}
public function networkOffersEpc:void{
app(OffersNetworkEpcHandler::class)->handle();
}
public function networkSurveys():void{
app(SurveysNetworkHandler::class)->handle();
}
public function networkSurveysCpm():void{
app(SurveysNetrworkCpmHandler::class)->handle();
}
public function networkSurveysEpc:void{
app(SurveysNetworkEpcHandler::class)->handle();
}
//...other handlers, like countryOffersCpm, toolSpecificOffersCpm and so on
}
SurveysNetrworkCpmStatsHandler:
/** This handle responsible of collectiong, calculating and storing network wide survey CPMs. We can't calculate CPM inside DB, so here we are going to use CpmCalculator */
class SurveysNetrworkCpmStatsHandler implements StatsHandlerInterface {
private $surveyImpressionsRepo;
private $statsRepo;
private $vcPointRepo;
private $calculator;
public function __construct(
SurveyImpressionRepositoryInterface $surveyImpressionRepository,
SurveyStatsRepositoryInterface $statsRepository,
VcPointRepositoryInterface $vcPointRepository,
CpmCalculator $calculator
){
$this->surveyImpressionsRepo = $surveyImpressionRepository;
$this->calculator = $calculator;
$this->vcPointRepo = $vcPointRepository;
$this->statsRepo = $statsRepository;
}
public function handle() {
$stats = [];
list($impressions, $conversions) = $this->fetchStatisticData();
foreach ($impressions as $impression) {
$sid = $impression->survey_id;
$conversion = $conversions->first(function($conversion) use ($sid) {
return $conversion->survey_id === $sid;
});
if(!isset($conversion)) {
continue;
}
$stat = new \SurveyNetworkCpmStat();
$stat->offer_id = $impression->offer_id;
$stat->survey_id = $sid;
$stat->mobile_cpm = $this->calculator->setConversionCount($conversion->conversions_count_mobile)->setImpressionsCount($impression->unique_impressions_count_mobile)->setPayoutSum($conversion->payout_sum_mobile)->calculate();
$stat->desktop_cpm = $this->calculator->setConversionCount($conversion->conversions_count_desktop)->setImpressionsCount($impression->unique_impressions_count_desktop)->setPayoutSum($conversion->payout_sum_desktop)->calculate();
$stat[] = $stat->toArray();
}
$this->store($stats)
}
private function fetchStatisticData(){
$impressions = $this->surveyImpressionsRepo->getImpressionsForNetworkCpm();
$conversions = $this->vcPointRepo->getConversionsForSurveyNetworkCpm();
return [$impressions, $conversions];
}
private function store($stst): bool{
$this->statsRepo->insert()
}
}
SurveysNetrworkStatsHandler:
/** This handle responsible of collectiong, calculating and storing all network wide survey stats.*/
class SurveysNetrworkStatsHandler implements StatsHandlerInterface {
private $cpmHandler;
private $epcHandler;
private $statsRepo;
public function __construct(
SurveysNetrworkCpmStatsHandler $cpmHandler,
SurveysNetrworkEpcStatsHandler $epcHandler,
SurveyStatsRepositoryInterface $statsRepository
){
$this->cpmHandler = $cpmHandler;
$this->epcHandler = $epcHandler;
$this->statsRepo = $statsRepository;
}
public function handle() {
$this->cpmHandler->handle();
$this->epcHandler->handle();
}
}
OffersNetrworkCpmStatsHandler:
etrworkCpmStatsHandler:
/** This handle responsible of collectiong, calculating and storing network wide offers CPMs. We can calculate CPM inside DB, so here do not need any Calculator */
class OffersNetrworkCpmStatsHandler implements StatsHandlerInterface {
private $surveyImpressionsRepo;
private $statsRepo;
public function __construct(
SurveyImpressionRepositoryInterface $surveyImpressionRepository,
SurveyStatsRepositoryInterface $statsRepository
){
$this->surveyImpressionsRepo = $surveyImpressionRepository;
$this->statsRepo = $statsRepository;
}
public function handle() {
$stats = [];
$stats = $this->fetchStatisticData();
$this->store($stats)
}
private function fetchStatisticData(){
return $this->surveyImpressionsRepo->getCpm();
}
private function store($stst): bool{
$this->statsRepo->insert()
}
}
CpmCalculator:
/** Class NetworkCpmCalculator. This object responsible for calculation of CPM. Formula to calculate cpm is payout_sum/(impressions_count/1000) */
class NetworkCpmCalculator implements StatsCalculatorInterface {
private $payoutSum = 0;
private $impressionsCount = 0;
private $conversionsCount = 0;
public function setPayoutSum(float $payoutSum = null):self{
$this->payoutSum = $payoutSum;
return $this;
}
public function setImpressionsCount(int $impressionsCount = null):self{
$this->impressionsCount = $impressionsCount;
return $this;
}
public function setConversionCount(int $conversionsCount = null):self{
$this->conversionsCount = $conversionsCount;
return $this;
}
public function calculate():int{
if(!$this->validate()) {
return null;
}
return $this->payoutSum/($this->impressionsCount/1000);
}
//validation here
}
I remove all validation logic here and interfaces to reduca amount of code.
Can anyone suggest any improvements, maybe I can use some patterns here? Thanks for any suggestions.

how to like value to %field_value% in sql or codeigniter?

I have a table named uri_table that contain:
id, uri_segment
1, /dir_name/bla-bla-1/
2, /dir_name/bla-bla-2/
3, /dir_name/bla-bla-3/
I want to get the pure link that only contain until controller_name and the controller param are not included. but when I use $_SERVER['URI_SEGMENT'] it will get the controller param too.
so I can't do this code below to search in my model:
function check_uri()
{
$this->db->like('uri_segment',$uri_segment,'after');
$id = $this->db->get('uri_table')->row_array()['id'];
return $id;
}
instead of:
function check_uri($request_uri=$_SERVER['URI_SEGMENT'])
{
//trim controller param that is numeric
for($i = strlen($request_uri)-1;$i > 0;$i--)
{
if(is_numeric($request_uri[$i]) || $request_uri[$i]=='/')
{
continue;
}
else
{
$request_uri = substr($request_uri,0,$i+1);
break;
}
}
$this->db->where('uri_segment',$request_uri);
$id = $this->db->get('uri_table')->row_array()['id'];
return $id;
}
This is my code right now but is also can remove param that is number if the $request_uri = '/dir_name/bla-bla-3/1/some_param/3' it'll return $id null. What can I do to remove the param/get uri without controller param or how to compare the $uri_segment to uri_segment ($this->db->like($uri_segment, '%uri_segment%'))?
Do one thing when you create a controller in that store the controller name like this:
class About extends CI_Controller {
// MVC config
var $PANEL = '';
var $CONTROLLER = 'about';
var $MODEL = 'mdl_about';
var $TITLE = 'page title';
var $LIST_PAGE_NAME = 'aboutus';
function About() {
parent::__construct();
//$this->load->model($this->MODEL, 'model');
}
function index() {
$this->load->view($this->LIST_PAGE_NAME);
}
}
So that above controller, model, page title and view page can be use anywhere is related to that controller.
To display the variable value use like this:
echo $this->CONTROLLER;
Or you can try this:
$this->router->fetch_class(); //for controller
$this->router->fetch_method(); //for method

Create different objects based on multiple parameters

I have a REST API. I need to create presentation (DTO) object, but the construction of this object depends on request - it differs in 15%.
I wonder what pattern should I use.
My case:
//presentation-DTO
class Item {
private $name;
private $price;
private $tags;
private $liked; //is Liked by logged user
...
public function __construct(Item $item, bool $liked, ...)
{
$this->name = $item->getName();
$this->price = $item->getPrice();
$this->tags = $item->getTags();
$this->liked = $liked;
...
}
}
When user is not logged in - I don't need $liked
When showing list of items - I don't need $tags
And there are more attributes that works as above.
My first idea was to use Builder principle.
$itemBuilder = new ItemBuilder();
$itemBuilder->setItem($item);
...
if($user) {
$itemBuilder->setUserLiked($userLiked);
...
}
return $itemBuilder->build();
It solves my problem with too many parameters in constructor.
But still, I also don't need all parameters to be constructed - eg. I don't need tags (on lists). As I use lazy load, I don't want my dto constructor to call them.
So I thought, maybe Factory.. but then my problem with too many (and optional) parameters is returning.
How will you solve this?
Sorry I don't have required points to make a comment hence an answer.
What are you trying to do with the Item class. Your class is Item and first parameter is also of type Item. I cannot visualizes how its going to work.
I will prefer to keep business login to set proper properties in a separate class:
/**
* A class for business logic to set the proper properties
*/
class ItemProperties {
private $item;
public $isLogin = false;
public $showList = false;
.....
public function __construct(Item &$item) {
// set all properties;
}
public function getProperties() {
$retVal = [];
if($this->isLogin == true) {
$retVal['liked'] = true;
}
if($this->showList == true) {
$retVal['tags'] = $this->item->getTags();
}
if(....) {
$retVal['...'] = $this->item->.....();
}
return $retVal;
}
}
/**
* DTO
*/
class Item {
public function __construct(ItemProperties $itemProps) {
$this->setItemProps($itemProps);
}
// If you prefer lazy loading here...maybe make it public
// and remove call from constructor.
private function setItemProps(&$itemProps) {
$properties = $itemProps->getProperties();
foreach($properties AS $propName => $propValue) {
$this->$propName = $propValue;
}
}
}
// Usage:
$itemProps = new ItemProperties($Item);
// set other properties if you need to...
$itemProps->isLogin = false;
$item = new Item($itemProps);

Edit profile page with 3 tables - Yii frameworks

I am new on Yii framework, so please i need some help where to start.
What i need is, action and module to display a form to a user, which his will be able to edit is own profile (with profile picture), so i have 3 table
user_account || user_personal || user_general
how can i build a form that insert and update those 3 table at once?
i try this:
This is what i did, but its still not saving the data even into 1 table.
public function actionUpdate() {
$model = new ProfileUpdate();
if(isset($_POST['ProfileUpdate']))
{
$model->attributes = $_POST['ProfileUpdate'];
if($model->validate())
{
$account = new Profile();
$account->userid = Yii::app()->user->id;
$account->name = $model->name;
$account->website = $model->website;
$account->category = $model->category;
$account->save();
$this->redirect('profile');
}
}
model:
class Profile extends CActiveRecord
{
public $userid;
public $name;
public $website;
public $category;
public static function model()
{
return parent::model(__CLASS__);
}
public function tableName()
{
return 'userinfo';
}
public function primaryKey()
{
return 'id';
}
public static function userExists($user)
{
return self::model()->countByAttributes( array('username'=>$user) ) > 0;
}
}
You can use all three models in a single function
for example:
In create function
$model_account = new user_account;
$model_personal= new user_personal;
$model_general = new user_general;
$this->render('create',array(
'model_account'=>$model_account, 'model_personal' => $model_personal, 'model_general' => $model_general
));
here the all three models pass by render to create page.
in form page you can use the every model attributes as fields
Like this
echo $form->textField($model_account,'account_name');
echo $form->textField($model_personal,'email');
echo $form->textField($model_general,'address');
In create function / Update function
$model_account->attributes = $_POST['user_account'];
$model_personal->attributes = $_POST['user_personal'];
$model_general->attributes = $_POST['user_general'];
if($model_account->validate() && $model_personal->validate() && $model_general->validate())
{
$model_account->save();
$model_personal->save();
$model_general->save();
}

How do I pass SQL database query from the Model to the Controller and then the View on Code Igniter 2.0.3?

I was trying to pass SQL values from Model to Controller but the value couldn't be passed.
This the code in my model file:
class Has_alert extends CI_Model {
function __construct()
{
parent::__construct();
}
function __get_query() {
$sql = 'alerts_get_alerts';
$query = $this->db->query($sql);
$row = $query->first_row();
$header_data['hasAlert'] = $row->active;
}
}
And this is the code in my controller file:
class Chart extends CI_Controller {
// Default Constructor
public function __construct() {
parent::__construct();
$this->load->helper('html');
$this->load->model('Has_alert', '', TRUE);
$this->Has_alert->__get_query();
//$sql = 'alerts_get_alerts';
//$query = $this->db->query($sql);
//$row = $query->first_row();
//$header_data['hasAlert'] = $row->active;
}
public function index()
{
//Data Arrays
$this->load->helper('html');
$header_data['page_title'] = 'Title';
$header_data['tabid'] = "home";
//Load the headtop.php file and get values from data array
$this->load->view('includes/headertop.php', $header_data);
$this->load->view('homepage');
$this->load->view('includes/newfooter.php');
}
I got this error message on my view file:
A PHP Error was encountered
Severity: Notice
Message: Undefined variable: hasAlert
Filename: includes/headertop.php
Line Number: 184
Does anyone know what the problem is? Thank you.
Model
function __get_query() {
$sql = 'alerts_get_alerts';
$query = $this->db->query($sql);
$row = $query->first_row();
return $row->active;
}
Controller
public function index(){
$this->load->model("Has_alert");
//Data Arrays
$this->load->helper('html');
$header_data['page_title'] = 'Title';
$header_data['tabid'] = "home";
$header_data['hasAlert'] = $this->Has_alert->__get_query();
//Load the headtop.php file and get values from data array
$this->load->view('includes/headertop.php', $header_data);
$this->load->view('homepage');
$this->load->view('includes/newfooter.php');
}
I'm assuming that things like "alerts_get_alerts" is pseudocode.