Laravel "same" code different results - laravel

I'm trying to guess what's different in this short code but I can't. One works an the other one returns:
Undefined property: Illuminate\Database\Eloquent\Builder::$join_books
First method, this one throws error:
public function selectBook(){
try{
BookUser::create(Input::all());
if(!BookUser::userJoinBooks()){
$user = User::eloquentUser();
$user->join_books = 1;
$user->save();
}
MyHelpers::sendSessionFlashMessages('El libro ha sido seleccionado', 'bg-success');
}
catch (Exception $e) {
$message = MyHelpers::exceptionCatch($e);
MyHelpers::sendSessionFlashMessages($message['message'], $message['css-class']);
}
return Redirect::back();
}
Two lines after this one I have the unselect method, looks like the same, but works fine:
public function unselectBook(){
try{
$book_user = BookUser::find(Input::get('id'));
$book_user->delete();
if(BookUser::userBooksCount() == 0){
$user = User::eloquentUser();
$user->join_books = 0;
$user->save();
}
MyHelpers::sendSessionFlashMessages('El libro ha sido eliminado', 'bg-success');
}
catch (Exception $e) {
$message = MyHelpers::exceptionCatch($e);
MyHelpers::sendSessionFlashMessages($message['message'], $message['css-class']);
}
return Redirect::back();
}
If I remove from SelectBook method "!BookUser::userJoinBooks()" in the if statement and use if(1) for example, it work's. I dont undestand why if I make the $user asigment after this static method it could be influence it.
This is the static method code:
public static function userJoinBooks($id = null){
$user_id = $id === null ? Sentry::getUser()->getId(): $id;
return User::where('id',$user_id)->join_books == 0 ? false : true;
}
And the other one too, may be help:
public static function userBooksCount($id = null){
$user_id = $id === null ? Sentry::getUser()->getId(): $id;
return BookUser::where('user_id',$user_id)->count();
}
And this is the eloquentUser method:
public static function eloquentUser(){
$sentry_user = Sentry::getUser();
return $user = User::findOrFail($sentry_user->id);
}
Really a can't remenber why I use this method, I soppose not to use Sentry::getUser in my code that if at some point I will use another user's library.
Thanks :)

The problem is this part of your code:
return User::where('id',$user_id)->join_books == 0 ? false : true;
I suppose you would want to use something like:
return User::findOrFail($user_id)->join_books == 0 ? false : true;

Related

Foreach Storing last data form array in Laravel. Help Plz

I have Tag table, Post Table and PostHasTag Table. But when I go to store my tags in, PostHasTag with post_id and tag_id.
I am using foreach loop for storing tags, but it just stored last tag. Now where is my problem?
public static function postHasTags($post_id, $tag_ids)
{
$store = new PostHasTag();
foreach ($tag_ids as $tag_id) {
$checkTag = PostHasTag::where('post_id', $post_id)->where('tag_id', $tag_id)->get();
if (count($checkTag) > 0) {
return back()->with('error', 'Tag already exists');
} else{
$store->post_id = $post_id;
$store->tag_id = $tag_id;
$store->save();
}
}
return $store;
}
Line $store = new PostHasTag(); should be inside foreach() loop, so it should look like this :
public static function postHasTags($post_id, $tag_ids)
{
foreach ($tag_ids as $tag_id) {
$checkTag = PostHasTag::where('post_id', $post_id)->where('tag_id', $tag_id)->get();
if (count($checkTag)) {
return back()->with('error', 'Tag already exists');
} else{
$store = new PostHasTag(); // Better to put it here
$store->post_id = $post_id;
$store->tag_id = $tag_id;
$store->save();
}
}
return $store;
}
But in this case you are returning only last created PostHasTag. If you need all of them, then push each PostHasTag in a collection and return it.

Laravel application freezes doesn't respond anymore

I have a laravel application that uses a while loop to process a txt file(6000 lines) line by line together with various helpers to manipulate each string. At the end of the manipulation it stores a record in db for each line. Everything works fine, the application process the entire file in a minute and returns the view indicated. The problem is that the application than freeze(not sure if this is the appropriate term), it keeps running and the browser ask repeatedly to wait or close the application.
I noticed also this message in the laravel server if it may help
[Wed Apr 21 10:28:26 2021] 127.0.0.1:50897 Closed without sending a request; it was probably just an unused speculative preconnection
Thanks to anyone who could help me.
This is the process:
$log = new UserActivityHelper;
$log->create(Config::get('constants.user_activities.FTP_FILE_PROCESSED_START'), 'test');
$file = fopen(Storage::path("1-2021.txt"), 'r');
while(!feof($file))
{
$line = fgets($file);
//call the method that validate the string
$string = new ValidateStringHelper($line); //FIRST HELPER
$string->validate();
//check the result of the validation
if($string->validated == false){
dd("out");
} elseif ($string->empty == true){
continue;
}else{
//save the validated array of substrings as variable
$my_arr = $string->validatedChars;
//check if the province exists or create it
$province = new ProvinceExistsHelper($my_arr['district']); //SECOND HELPER
$province->check_if_exists_or_create();
if($province->new_province == true) {
$log = new UserActivityHelper;
$log->create(Config::get('constants.ftp_process.FTP_PROVINCE_CREATED'), "Creata nuova provincia con id {$province->district_id}");
self::message('yellow', "Attenzione. Nell'elaborazione sono state create nuove provincie, controllare le impostazioni.");
}
//manipolation of name and lastname
$name = ucwords(strtolower($my_arr['name_lastname']));
//check if the person already exists or create it (passing fiscal code, name and district_id)
$person = new PersonExistsHelper($my_arr['fiscal_code'], $name, $province->district_id); //THIRD HELPER
$person->check_if_exists_or_create();
$newMovement = new Movement;
$newMovement->person_id = $person->person_id;
if(array_key_exists('level', $my_arr)){
$newMovement->level = $my_arr['level'];
}
...
try {
$newMovement->save();
} catch (\Throwable $exception) {
report($exception);
return;
}
}
}
fclose($file);
$log = new UserActivityHelper;
$log->create(Config::get('constants.user_activities.FTP_FILE_PROCESSED_END'), 'test');
return view('ftp.test');
Helpers called:
class ValidateStringHelper
{
public $line;
public $empty = false;
public $validated = false;
public $validationErrors = array();
public $validatedChars = array();
public function __construct($line){
$this->line = $line;
}
public function validate(){
if ($this->line!="")
{
if(strlen($this->line) >= 186)
{
//substrings
$district = trim(substr($this->line, 0, 2));
$trade_union_tax_code = trim(substr($this->line, 2, 3));
...
//validation
//check if validated
$this->validatedChars['district'] = $district;
$this->validatedChars['trade_union_tax_code'] = $trade_union_tax_code;
...
//filter all non empty string values and not all zero strings
$filter_arr = array_filter($this->validatedChars, fn($value) => $value !== '' && preg_filter('/^(?!0*$).*$/', '$0', $value));
$this->validatedChars = $filter_arr;
$this->validated = true;
return $this->validated;
//return $this->validatedChars;
//eturn $this->validated;
} else {
$this->validationErrors[] = "string_length";
return $this->validated;
}
} else {
$this->empty = true;
return $this->empty;
}
}
class PersonExistsHelper
{
public $name_lastname;
public $fiscal_code;
public $district_id;
public $new_person = false;
public $person_id;
public function __construct(string $fiscal_code, string $name_lastname, string $district_id){
$this->fiscal_code = $fiscal_code;
$this->name_lastname = $name_lastname;
$this->district_id = $district_id;
}
public function check_if_exists_or_create()
{
$person = Person::where('fiscal_code', '=', $this->fiscal_code)->first();
if($person == NULL)
{
$this->new_person = true;
$newPerson = new Person;
$newPerson->name_lastname = $this->name_lastname;
$newPerson->district_id = $this->district_id;
$newPerson->fiscal_code = $this->fiscal_code;
$newPerson->created_by = Config::get('constants.people_creation.FTP_PROCESS');
$newPerson->save();
$this->person_id = $newPerson->id;
return $this->person_id;
} else{
$this->person_id = $person->id;
return $this->person_id;
}
}
}
class ProvinceExistsHelper
{
public $district_id;
public $district_code;
public $new_province = false;
public function __construct($district_code){
$this->district_code = $district_code;
}
public function check_if_exists_or_create()
{
//check if the province is in the Provinces table
$province = Province::where('code', '=', $this->district_code)->first();
if(!isset($province))
{
$this->new_province = true;
$newProvince = new Province;
$newProvince->name = $this->district_code;
$newProvince->code = $this->district_code;
$newProvince->save();
$this->district_id = $newProvince->id;
return $this->district_id;
} else {
//if yes, just return the id of the province
$this->district_id = $province->id;
return $this->district_id;
}
}
}

Laravel Eloquent, "inheritance" override fields from parent

Is there any way in Eloquent to have a model which has some sort of parent model, where both have an identical field, nullable on the child. And if I get the value $child->field I get the childs value if it's not null, otherwise I get the parent value? Something like this:
$parent = new Parent();
$parent->info = 'parent';
$parent->save();
$child = new Child();
$child->info = 'child';
$child->parent()->associate($parent);
$child->save();
echo $child->info
Prints 'child'
And opposite:
$parent = new Parent();
$parent->info = 'parent';
$parent->save();
$child = new Child();
$child->parent()->associate($parent);
$child->info = null;
$child->save();
echo $child->info
Prints 'parent'
It must be a pattern somewhere to have one table rows values 'overrule' another, I just can't seem to find what to search for.
You simply need a custom accessor on the model of your choice:
class Child
{
public function getInfoAttribute($value)
{
if ($value === null) {
return $this->parent->info;
}
return $value;
}
}
This will allow you to still access the property via $child->info.
Please be aware that this will not cast the attribute value according to the $casts array. If you need this casting logic as well, you should use a custom getter method instead of the magic accessor:
class Child
{
public function getInfo()
{
$info = $this->info;
if ($info === null) {
$info = $this->parent->info;
}
return $info;
}
}
If you need to multiple properties, you can either duplicate the code and put it into a trait to remove the clutter from your model. Or instead, you can try overriding the magic __get($key) method:
class Child
{
$parentInheritedAttributes = ['info', 'description'];
// solution 1: using normal model properties like $child->info
public function __get($key)
{
if (in_array($key, $this->parentInheritedAttributes)) {
$value = parent::__get($key);
if ($value === null) {
// this will implicitely use __get($key) of parent
$value = $this->parent->$key;
}
return $value;
}
return parent::__get($key);
}
// solution 2: using getters like $child->getInfo()
public function __call($method, $parameters)
{
if (\Illuminate\Support\Str::startsWith($method, 'get')) {
$attribute = \Illuminate\Support\Str::snake(lcfirst(substr($method, 3)));
in_array($attribute, $this->parentInheritedAttributes)) {
$value = $this->$attribute;
if ($value === null) {
$value = $this->parent->$attribute;
}
return $value;
}
}
}
}

How to execute certain function after some time?

I have this function where user can reject other user.
public function rejectPersonalUser($id){
$user = PersonalUser::findOrFail($id);
$user->approved = 0;
$user->business_user_id = NULL;
$user->save();
return redirect()->back()->withFlashMessage('User has been rejected successfully!!');
}
Now what i want is to check if user reject other user after 7 days if its not to call other function.
public function setUser($id){
$user = PersonalUser::findOrFail($id);
if($user->approved == 0 && $user->business_user_id != NULL){
$user->approved = 0;
$user->business_user_id = NULL;
$user->save();
}
}
You can use Task Scheduling, If you want it to run after some time period.
You could just use like:
$schedule->call(function () {
//your block of codes here..
})->weekly()->mondays()->at('13:00');
Or more specifically for your needs you could call to a function that doesn't inject any parameters and try to call the user from there.
$schedule->call(function () {
//call someScheduleTaskForUser() from here.
})->weekly()->mondays()->at('13:00');
public function someScheduleTaskForUser() {
//call the setUser() function from here...
}
// This function could reside somewhere.
public function setUser($id){
$user = PersonalUser::findOrFail($id);
if($user->approved == 0 && $user->business_user_id != NULL){
$user->approved = 0;
$user->business_user_id = NULL;
$user->save();
}
}

Laravel if statement with other variable value

I try to get data from a model, but the value of the column name from the data model is in another variable. Here's a little preview what I try to achieve:
switch($device->target_objectclass_id) {
case 10:
$handler = Servers::findOrFail($device->target_object_id);
default:
break;
}
if($handler->($condition->column) ($condition->condition) ($condition->value)) {
//process the other data it it's true
}
Example of what should be displayed:
if($handler->status == 1) {
//handle data
}
The reason behide this is a little bit complicated. The user's need to create triggers which will be executed.
Btw, all possible conditons are possible.
For example:
check table where column condition value
check servers where status == 1
Hope someone has an answer if you can understand my problem...
I'm not sure how feasible it is to dynamically insert the operator into an expression like that. However, with a limited set of operators, you could do something like this:
class YourClass
{
public function yourMethod()
{
// Your model instance to test, I've just used a stdClass as an example
$instance = new stdClass;
$instance->status = 1;
// Your condition instance
$condition = new stdClass;
$condition->column = 'status';
$condition->condition = '==';
$condition->value = '1';
if ($this->compare($instance, $condition)) {
// This code will execute then $instance->status == '1'
}
}
public function compare($instance, $condition)
{
$operator = $condition->condition;
$condition = $condition->column;
$value = $condition->value;
switch ($operator) {
case '==':
return $instance->$column == $value;
case '!=':
return $instance->$column != $value;
case '>':
return $instance->$column > $value;
case '<':
return $instance->$column < $value;
case '>=':
return $instance->$column >= $value;
case '<=':
return $instance->$column <= $value;
default:
throw new \Exception('Unsupported operator');
}
}
}
Or a nicer, class based way of doing it...
class Conditional
{
protected $operator;
protected $column;
protected $value;
protected $supportedOperators = [
'==' => 'equals',
'!=' => 'notEquals'
];
public function __construct($column, $operator, $value)
{
$this->column = $column;
$this->operator = $operator;
$this->value = $value;
}
public function check($instance)
{
$method = $this->getMethod();
$instanceValue = $instance->{$this->column};
return $this->$method($instanceValue, $this->value);
}
private function getMethod()
{
if (isset($this->supportedOperators[$this->operator]) && method_exists($this, $this->supportedOperators[$this->operator])) {
return $this->supportedOperators[$this->operator];
}
throw new \Exception('Unsupported operator');
}
protected function equals($one, $two)
{
return $one == $two;
}
protected function notEquals($one, $two)
{
return $one != $two;
}
}
Then you can use it like this...
$instance = new stdClass;
$instance->status = 1;
$conditional = new Conditional('status', '==', 1);
if ($conditional->check($instance)) {
// Execute if $instance->status == 1.
}

Resources