Prestashop integrate javascript to custom page - prestashop-1.7

I have created a custom page in Prestashop 1.7.X by using an own controller. How can I load a custom javascript file?
<?php
class MyPageControllerCore extends FrontController{
public $php_self = 'mypage';
public $ssl = true;
public function initContent(){
parent::initContent();
$this->setTemplate('mypage');
}
public function setMedia(){
parent::setMedia();
$this->context->controller->addJS(_THEME_JS_DIR_.'about_us.js');
}
}

Standard way:
1- Generate new module that has frontController
2- Load your custom javascript file from your module
<?php
class ModulenameMypageModuleFrontController extends ModuleFrontController
{
public $php_self = 'mypage';
public $ssl = true;
public function initContent(){
parent::initContent();
$this->setTemplate('mypage.tpl');
}
public function setMedia(){
parent::setMedia();
$this->context->controller->addJS(_PS_MODULE_DIR_.'/views/js/about_us.js');
}
}

Related

How can I avoid repeating this line in all my methods?

I am working on a blogging application in Laravel 8.
I have a settings table from which I pull the directory name of the current theme.
class ArticlesController extends Controller {
public $theme_directory;
public function index() {
// Theme _directory
$this->theme_directory = Settings::all()[0]->theme_directory;
// All articles
$articles = Article::all();
return view('themes/' . $this->theme_directory . '/templates/index', ['articles' => $articles]);
}
public function show($slug) {
// Theme _directory
$this->theme_directory = Settings::all()[0]->theme_directory;
// Single article
$article = Article::where('slug', $slug)->first();
return view('themes/' . $this->theme_directory . '/templates/single', ['article' => $article]);
}
}
The problem
A you can see, the line $this->theme_directory = Settings::all()[0]->theme_directory is repeted in both methods (and would be repeted in others in the same way).
Question
How can I avoid this repetition (and make my code DRY)?
Inheritance approach
Inheritance for a controller would avoid you from repeating it.
abstract class CmsController extends Controller{
protected $themeDirectory;
public function __construct()
{
$this->themeDirectory= Settings::first()->theme_directory ?? null;
}
}
Extend it and you can access it like you have always done.
class ArticlesController extends CmsController
{
public function index() {
dd($this->themeDirectory);
}
}
Trait
Use traits which is partial classes, done by just fetching it, as it is used in different controllers the performance is similar to saving it to an property as it is never reused.
trait Themeable
{
public function getThemeDirectory()
{
return Settings::first()->theme_directory ?? null;
}
}
class ArticlesController extends CmsController
{
use Themeable;
public function index() {
dd($this->getThemeDirectory());
}
}
Static function on model
If your models does not contain to much logic, a static function on models could also be a solution.
class Setting extends model
{
public static function themeDirectory()
{
return static::first()->theme_directory ?? null;
}
}
class ArticlesController extends CmsController
{
use Themeable;
public function index() {
dd(Setting::themeDirectory());
}
}

Override Eloquent Relation Create Method

I want to override create method, but with relation, it didn't touch the create method.
There are Two Models:
class User extends Model
{
public function user_detail()
{
return $this->hasOne(UserDetail::class);
}
}
class UserDetail extends Model
{
public static function create(array $attributes = [])
{
//I was trying to do something like
/*
if(isset($attributes['last_name']) && isset($attributes['first_name']))
{
$attributes['full_name']=$attributes['first_name'].' '.$attributes['last_name'];
}
unset($attributes['first_name'],$attributes['last_name']);
*/
Log::debug('create:',$attributes);
$model = static::query()->create($attributes);
return $model;
}
}
When I use UserDetail::create($validated), and there is a log in laravel.log, so I know the code touched my custom create method.
But if I use
$user = User::create($validated);
$user->user_detail()->create($validated);
There is no log in laravel.log, which means laravel didn't touch the create method, then how I supposed to do to override create method under this circumstance?(I'm using laravel 5.7)
Thank you #Jonas Staudenmeir, after I read the documentation, here is my solution.
If the $attributes are not in protected $fillable array, then I do it in the __construct method.
class UserDetail extends Model
{
protected $fillable=['full_name','updated_ip','created_ip'];
public function __construct(array $attributes = [])
{
if (isset($attributes['first_name']) && isset($attributes['last_name'])) {
$attributes['full_name'] = $attributes['first_name'].' '.$attributes['last_name'];
}
parent::__construct($attributes);
}
}
Otherwise, I do it in Observer.
namespace App\Observers;
use App\Models\UserDetail;
class UserDetailObserver
{
public function creating(UserDetail $userDetail)
{
$userDetail->created_ip = request()->ip();
}
public function updating(UserDetail $userDetail)
{
$userDetail->updated_ip = request()->ip();
}
}
Register Observer in AppServiceProvider.
namespace App\Providers;
use App\Models\UserDetail;
use App\Observers\UserDetailObserver;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
UserDetail::observe(UserDetailObserver::class);
}
}
I choose Observer instead of Event&Listener is for easy maintenance.

Laravel - check if the Eloquent object is found inside model

In my controller I would like to have this:
class TodoController extends Controller {
public function getDone($todoId)
{
Todo::find($todoId)->markAsDone();
}
}
model I have:
class Todo extends Eloquent {
public function markAsDone()
{
if (???) {
$this->is_done = 1;
$this->save();
}
}
}
How can I check if the model is found and is present in $this?
In your case, checking the existence of ToDo object can only be done in controller. Because in your current code Todo::find($todoId)->markAsDone(); if the $todoId is invalid, you will be have BIG error, trying to get property of non-object. So its better to do this.
class TodoController extends Controller {
public function getDone($todoId)
{
$todo = Todo::find($todoId);
if ($todo) {
$todo->markAsDone();
}
}
}
And in your model
class Todo extends Eloquent {
public function markAsDone()
{
$this->is_done = 1;
$this->save();
}
}

Laravel Multiple module using one Controller

Now I have few modules created like Product, Sale, Category. I found out they actually using same function with similar process. For example update() in Controller :
Category
public function update($id)
{
$instance = Category::findOrFail($id);
$instance->fill(Input::all())->save();
}
Product
public function update($id)
{
$instance = Product::findOrFail($id);
$instance->fill(Input::all())->save();
}
How can I join it together to BaseController by just make the Model dynamic?
Something like this:
abstract class ResourceController extends BaseController
{
protected $entity;
public function __construct(Model $entity){ //or Eloquent, depending on your import alias
$this->entity = $entity;
}
public function update($id)
{
$instance = $this->entity->findOrFail( $id );
$instance->fill( Input::all() )->save();
}
}
class ProductController extends ResourceController{
public function __construct(Product $entity){
parent::__construct($entity);
}
}
class CategoryController extends ResourceController{
public function __construct(Category $entity){
parent::__construct($entity);
}
}

Type hinting parent::__construct() arguments in controllers

I've got a BaseController in a Laravel Framework based App with the following code:
class BaseController extends Controller {
public function __construct(Credentials $credentials) {
$this->credentials = $credentials;
}
Then, all my other controllers will Extend the BaseController:
class PostController extends BaseController {
public function __construct(PostRepository $post)
{
$this->post = $post;
parent::__construct();
}
However, I'd need to type hint the Credentials Class in the parent::__construct(); of all my controllers. Is there any way to avoid that?
Thanks in advance
I can solve it using the following code:
class BaseController extends Controller {
public function __construct()
{
$this->credentials = App::make('Credentials'); // make sure to use the fully qualified namespace of Credentials if need be
}
}

Resources