How would you do that with Eloquent - Laravel 5.2 - laravel-5

I have this logic in a controller :
// hydratation part 1 (cf son modele)
$matiere->fill($request->all());
// hydratation part 2 with attributes not in the POST
$matiere->id_ecole = Session::get('id_ecole');
$request->has('matiere_inactive') ? $matiere->matiere_inactive = '1' : $matiere->matiere_inactive = null;
if ($matiere->exists) {
$matiere->auteur_modif = Session::get('nom').' '.Session::get('prenom');
} else {
$matiere->auteur_creation = Session::get('nom').' '.Session::get('prenom');
}
I think that the part 2 could be present in the model , instead of the controller (I like to have 'brief' controller).
Is it a good idea ?
If yes how could I do that ?
My model is :
class Matiere extends Model {
protected $table = 'matiere';
protected $primaryKey = 'id_matiere';
protected $fillable = [
'id_matiere',
'code_court_matiere',
'libelle_matiere'
];
public function setCodeCourtMatiereAttribute($value)
{
$this->attributes['code_court_matiere'] = strtoupper($value);
}
public function setLibelleMatiereAttribute($value)
{
$this->attributes['libelle_matiere'] = ucwords($value);
}
}

Laravel 5. 3
you can do that by creating a method on Matiere model.
Here is a simple example:
ExampleController.php
$mat = new \App\Matiere();
$feedback = $mat->addm($request);
Matiere.php
public function addm($request)
{
$this->id_ecole = \Session::get('id_ecole');
$request->has('matiere_inactive') ? $this->matiere_inactive = '1' : $this->matiere_inactive = null;
$this->save();
return $this->id;
}

Related

Create Join Between Tables Laravel

I Have 2 tables : Posts - Comment
I Want to Make Relation Between These 2 Tables and Need to Update The Comment That Has "1" Post_ID :
Route:
Route::get('join', 'JoinController#Join');
Controller :
public function Join()
{
$Comment = Posts::find(1)->Comment;
$Comment->Title = "JOIN";
$Comment->save();
}
Posts Model :
public function Comment()
{
return $this->hasOne('App\Comment');
}
Comment Model :
public function Posts()
{
return $this->belongsTo('App\Posts');
}
but i recieve this error :
Trying to get property of non-object
Do this instead:
$comment = new Comment;
$comment->Title = 'JOIN';
#comment->post_id = 1;
$comment->save();
Or you can use create() method:
$Comment = Posts::find(1)->Comment()->create(['Title' => 'JOIN']);
If you'll use create() method, make sure Title is in the $fillable array.
$Comment = Posts::find(1)->Comment()->first();
$Comment->Title = "JOIN";
$Comment->save();

Laravel 5: directory-elements sort by name in a hasMany relationship

I need to Sort folders ($data['contents']) by relationship langs() where lang_id == 1 How can I do that? Thanks.
In Model Folder:
class Folder extends Model
{
protected $fillable = ['active', 'date', 'path', 'slug'];
public function langs()
{
return $this->hasMany('App\Models\LangFolder');
}
}
In Model LangFolder:
class LangFolder extends Model
{
protected $fillable = ['folder_id', 'lang_id', 'name', 'description'];
public function folder()
{
return $this->belongsTo('App\Models\Folder');
}
}
In Controller:
public function folders()
{
// Sort folders ($data['contents']) by relationship langs() where lang_id == 1
$data['folders'] = Folder::all();
$data['langs'] = Lang::all();
$directory = 'library/';
$elements = array_diff(scandir($directory), array('..', '.'));
foreach($elements as $element) {
if (is_dir($directory . '/' . $element)) {
$content_element = Folder::where('slug', $element)->first();
$data['contents'][] = $content_element;
}
}
return view('web.library.index', compact('data'));
}
If you want to order from a relation, you must use Collection instead of Eloquent, for example:
$orderedLangs = $folder->langs->sortBy('lang_id');
I have finally added the field "name" of the relationship to the array, and I have converted the array into a collection, and then, I have sorted by 'name' case insensitive. Maybe there is another cleaner solution. This works:
Controller:
foreach($elements as $element){
if(is_dir($directory.'/'.$element)){
$content_element = Folder::where('slug', $element)->first();
$contenidos[] = $content_element;
}else{
$data['documents'][] = Document::where('path', $directory.'/'.$element)->first();
}
}
foreach($contenidos as $contenido){
foreach($contenido->langs as $lang){
if($lang->lang_id == '1'){
$contenido->name = $lang->name;
}
}
$data['contents'][]= $contenido;
}
$data['contents']=collect($data['contents'])->sortBy('name', SORT_NATURAL|SORT_FLAG_CASE);

Laravel get relationship model within object after save()

I am using laravel 4.2.
I have two models as below :
class User extends Eloquent{
protected $table = 'users';
public function user_card_details(){
return $this->hasMany('User_card_details');
}
}
And
class User_card_details extends Eloquent {
protected $table = 'user_card_details';
public $timestamps = true;
public $softdeletes = true;
public function user(){
return $this->belongsTo('User')->first();
}
}
And I can save the relationship record using :
$user_card_details = new User_card_details();
$user_card_details->card_number = Input::get('card_number');
$user_card_details->card_exp_month = Input::get('card_expires_m');
$user_card_details->card_exp_year = Input::get('card_expires_y');
$user_card_details->card_cvv = Input::get('card_cvv');
$user->user_card_details()->save($user_card_details);
Up to this it works fine for me.
After save() , I want the user object should be populated with user_details.
So if I want to use the properties, I can use it like :
echo $user->user_card_details->card_number;
But it is not working now.
Any suggestions?
Thanks
You have to remove the () to get the actual model or collection:
echo $user->user_card_details->card_number;
When you're calling the actual function, you'll receive an instance of the Query builder.
Also, it seems that you're not persisting your $user_card_details-object before you try to bind it to your user:
$user_card_details = new User_card_details();
$user_card_details->card_number = Input::get('card_number');
$user_card_details->card_exp_month = Input::get('card_expires_m');
$user_card_details->card_exp_year = Input::get('card_expires_y');
$user_card_details->card_cvv = Input::get('card_cvv');
$user_card_details->save(); //Added this line.
$user->user_card_details()->save($user_card_details);
The more correct way would be:
$user_card_details = [
'card_number' => Input::get( 'card_number' ),
'card_exp_month' => Input::get( 'card_expires_m' ),
'card_exp_year' => Input::get( 'card_expires_y' ),
'card_cvv' => Input::get( 'card_cvv' ),
];
$userCardDetailObj = $user->user_card_details()->create( $user_card_details );
Now, your User_card_detail-instance will be available as the returned object.

Laravel , suddenly query error

I used a code in my Basecontroller to share data with all the views ( for footer and header informations ) , it worked great but suddenly i was working on something totally different and i've got an error : No query results for model [Variable]
Can't understand why i didn't even modify my BaseController.
Here is my Base Controller :
public function __construct(){
$this->getVariable('horaire');
$this->getVariable('facebook');
$this->getVariable('contact');
$this->getVariable('twitter');
$main_slider = MainSlider::all();
View::share('main_slider',$main_slider);
}
public function getVariable($setting)
{
$variables[$setting] = Variable::where('name', $setting)->FirstOrFail();
$values[$setting] = $variables[$setting]->value;
View::share($setting, $values[$setting]);
}
And what I was working on
Class VariablesController extends BaseController {
public function settings(){
$settings['about'] = Variable::where('name','about')->FirstOrFail();
$settings['contact'] = Variable::where('name','contact')->FirstOrFail();
$settings['horaire'] = Variable::where('name','horaire')->FirstOrFail();
$settings['legals'] = Variable::where('name','legals')->FirstOrFail();
$settings['facebook'] = Variable::where('name','facebook')->FirstOrFail();
$settings['twitter'] = Variable::where('name','twitter')->FirstOrFail();
$settings['contact_email'] = Variable::where('name','contact_email')->FirstOrFail();
return View::make('admin.settings',compact('settings'));
}
public function update(){
$inputs['facebook'] = e(Input::get('facebook'));
$inputs['twitter'] = e(Input::get('twitter'));
$inputs['contact_email'] = e(Input::get('contact_email'));
$inputs['legals'] = e(Input::get('legals'));
$inputs['horaire'] = e(Input::get('horaire'));
$inputs['contact'] = e(Input::get('contact'));
$inputs['about'] = e(Input::get('about'));
foreach($inputs as $name => $input){
echo "$name => $input";
}
}
And my Variable model :
<?php
class Variable extends \Eloquent {
protected $guarded = ['id','created_at','protected_at'];
protected $table = 'variables';
}
Thank you for your helps

How to cache model attributes in Laravel

In my current configuration, a user's email is stored on a remote server that I need to hit with a curl quest.
Luckily, I only need the email once a day when a certain process runs. However, when that process does run it will need to reference the email multiple times.
This is the current accessor I have set up for email. The problem is the curl request is being called every time I use $user->email. What's the best way to avoid this?
in UserModel:
public function getEmailAttribute(){
$curl = new Curl;
$responseJson = $curl->post('https://www.dailycred.com/admin/api/user.json',array(
'client_id'=>getenv('dailycredId')
,'client_secret'=>getenv('dailycredSecret')
,'user_id'=>$this->id
));
$response = json_decode($responseJson);
return $response->email;
}
private $cached_email = false;
public function getEmailAttribute(){
if ($this->cached_email){
// if set return cached value
return $this->cached_email;
}
// get the email
$curl = new Curl;
$responseJson = $curl->post('https://www.dailycred.com/admin/api/user.json',array(
'client_id'=>getenv('dailycredId')
,'client_secret'=>getenv('dailycredSecret')
,'user_id'=>$this->id
));
$response = json_decode($responseJson);
// cache the value
$this->cached_email = $response->email;
// and return
return $this->cached_email;
}
Depending on your use case make adjustments (ie. session, cache , static property...).
Extend a the Eloquent Model class
namespace App\Models\Utils;
use Illuminate\Database\Eloquent\Model as OldModel;
class MyModel extends OldModel
{
private $cachedAttributes = [];
public function getCachedAttribute(string $key, Callable $callable)
{
if (!array_key_exists($key, $this->cachedAttributes)) {
$this->setCachedAttribute($key, call_user_func($callable));
}
return $this->cachedAttributes[$key];
}
public function setCachedAttribute(string $key, $value)
{
return $this->cachedAttributes[$key] = $value;
}
public function refresh()
{
unset($this->cachedAttributes);
return parent::refresh();
}
}
make your class
class ElementWithEmail extends MyModel
{
const ATTRIBUTE_KEY_FOR_EMAIL = 'Email';
public function getEmailAttribute(){
$key = self::ATTRIBUTE_KEY_FOR_EMAIL;
$callable = [$this, 'getEmail'];
return $this->getCachedAttribute($key, $callable);
}
protected function getEmail()
{
$curl = new Curl;
$responseJson = $curl->post('https://www.dailycred.com/admin/api/user.json',array(
'client_id'=>getenv('dailycredId')
,'client_secret'=>getenv('dailycredSecret')
,'user_id'=>$this->id
));
$response = json_decode($responseJson);
return $response->email;
}
}
Call it from your code
$element = new ElementWithEmail();
echo $element->email;

Resources