difference between Mage::app and Mage:: in Magento - magento

Can any body say what is the difference between
Mage:app and Mage::
eg:
Mage::getModel('catalog/product');
Mage::app->getLayout->createBlock('catalog/product_view');
if i try like this
Mage::app->getModel('catalog/product');
it throws a fatal error
What is the basic difference?

As a more general explanation and further to Alan's answer Mage::app() and Mage::getModel() are both static methods of the Mage class (app/Mage.php).
The Mage::app() function is used to bootstrap your Magento application (setting up configuration, autoloading etc) and is useful when wanting to access Magento models in your own custom script for example.
It is a static method so it can also be called at any point in your application to return the current Mage_Core_Model_App object which you can use for example to get current configuration values e.g. Mage::app()->getStore() will return the current Mage_Core_Model_Store store object.
Mage::app() is similar to Mage::run() found in your index.php file. The difference is that Mage::run() will amongst other things also invoke the MVC, routing etc part of your application as per default and control the request/response directing you to a page and instantiating the blocks and layout template rendering.
Mage::getModel() is simply a factory method that will return a new instance of a class based on the class alias you provide. For example Mage::getModel('customer/customer') will return a new Mage_Customer_Model_Customer object. If you want the same object back each time throughout your request you can use Mage::getSingleton() instead.

When you say
Mage::getModel('catalog/product');
You're calling the static method getModel on the class Mage
#File: app/Mage.php
public static function getModel($modelClass = '', $arguments = array())
{
return self::getConfig()->getModelInstance($modelClass, $arguments);
}
When you say
Mage::app->getModel('catalog/product');
you're going to get a fatal error, because that's invalid PHP.
However, if you say
$app = Mage::app();
You're calling the static method app on the Mage class
public static function app($code = '', $type = 'store', $options = array())
{
if (null === self::$_app) {
self::$_app = new Mage_Core_Model_App();
self::setRoot();
self::$_events = new Varien_Event_Collection();
self::$_config = new Mage_Core_Model_Config();
Varien_Profiler::start('self::app::init');
self::$_app->init($code, $type, $options);
Varien_Profiler::stop('self::app::init');
self::$_app->loadAreaPart(Mage_Core_Model_App_Area::AREA_GLOBAL, Mage_Core_Model_App_Area::PART_EVENTS);
}
return self::$_app;
}
which will return a Mage_Core_Model_App object, which will let you call any method on the class/object at
app/code/core/Mage/Model/App.php

Related

Integrate Twig with CodeIgniter 4

I used Twig with Symfony and I really loved it. I now have a CodeIgniter project and I want to integrate Twig with it.
I installed the latest versions of CodeIgniter and Twig via Composer and and followed this tutorial but I believe the code in the tutorial is for CI v3.
Could anyone who has integrated Twig with CI v4 help me with the proper code please.
UPDATE
solution below!
Try this I hope it will help you
Install Composer and run the following command to get the latest version:
composer require "twig/twig:^3.0"
Then after installation add this line of code to the baseController initController method just after the parent::initController, just like the code below
namespace App\Controllers;
use CodeIgniter\Controller;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Psr\Log\LoggerInterface;
class BaseController extends Controller
{
protected $helpers = [];
protected $twig;
// protected $helper = [];
public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger)
{
parent::initController($request, $response, $logger);
$appPaths = new \Config\Paths();
$appViewPaths = $appPaths->viewDirectory;
$loader = new \Twig\Loader\FilesystemLoader($appViewPaths);
$this->twig = new \Twig\Environment($loader, [
'cache' => WRITEPATH.'/cache/twig',
]);
}
}
So with this now you can call the view files in other controllers extends to parent controller BaseController
e.g
namespace App\Controllers;
class Home extends BaseController
{
public function index ()
{
// To load a template from a Twig environment, call the load() method which returns a \Twig\TemplateWrapper instance:
$template = $this->twig->load('index.html');
// To render the template with some variables, call the render() method:
return $template->render(['the' => 'variables', 'go' => 'here']);
// The display() method is a shortcut to output the rendered template.
// OR You can also load and render the template in one fell swoop:
return $this->twig->render('index.html', ['the' => 'variables', 'go' => 'here']);
// If a template defines blocks, they can be rendered individually via the renderBlock() call:
return $template->renderBlock('block_name', ['the' => 'variables', 'go' => 'here']);
// Note any of them above will work
}
}
If you still want to use view() with twig like codeigniter 4 default view function you can modify the Common.php file in app directory
by adding this block of code below.
if (!function_exists('view'))
{
function view($tpl, $data = []) {
$appPaths = new \Config\Paths();
$appViewPaths = $appPaths->viewDirectory;
$loader = new \Twig\Loader\FilesystemLoader($appViewPaths);
$twig = new \Twig\Environment($loader, [
'cache' => WRITEPATH.'/cache/twig',
]);
if (!stripos($tpl, '.twig')) {
$tpl = $tpl . '.twig';
}
return $twig->render($tpl, $data);
}
}
Then in controller call it like this
return view('index', ['name' => 'Chibueze Agwu'])
Then in view file index.twig
<!DOCTYPE html>
<html>
<head>
<title>My Webpage</title>
</head>
<body>
<h1>My Webpage</h1>
{{ name }}
</body>
</html>
This will output
My Webpage
Chibueze Agwu
I haven't test this code but I hope it will work. If not call my attentions.
In order to obey the the rule of DRY (DO NOT REPEAT YOURSELF), you can go ahead to improve the code I will do that later
I found the solution some time ago and I'm posting it in case some people stumble across the question.
First of all, all your controllers must extend BaseController; this controller is available by default when you install CodeIgniter 4.
Create a custom helper file and put in [project-name]/appstarter/app/Helpers.
IMPORTANT
the name of your helper must be [name]_helper.php or it will not work!
for example mine is called custom_helper.php
Create the following function in the custom helper you just created:
use Twig\Environment;
use Twig\Extension\DebugExtension;
use Twig\Loader\FilesystemLoader;
use Twig\TwigFilter;
if (!function_exists('twig_conf')) {
function twig_conf() {
// the follwing line of code is the only one needed to make Twig work
// the lines of code that follow are optional
$loader = new FilesystemLoader('Views', '../app/');
// to be able to use the 'dump' function in twig files
$twig = new Environment($loader, ['debug' => true]);
$twig->addExtension(new DebugExtension());
// twig lets you create custom filters
$filter = new TwigFilter('_base_url', function ($asset) {
return base_url() . '/' . $asset;
});
$twig->addFilter($filter);
return $twig;
}
}
NOTE
before creating any custom filter, make sure Twig doesn't already has one built-in.
Now in the BaseController you'll find an empty array called $helpers. You must put the name of your custom helper in it. Mine is called custom_helper.php; so the code looks like this for me:
protected $helpers = ['custom'];
Just below the array you'll find the constructor for BaseController and this is where the Twig library will be initialized; by calling the function you created in your custom helper:
public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger) {
parent::initController($request, $response, $logger);
$this->twig = twig_conf();
}
Now you are good to go! To render your twig files in any controller:
return $this->twig->render('twig_name', $dataArray);
Try this I hope it will help you.
Install Composer and run the following command to get the latest version:
composer require "twig/twig:^3.0"

Laravel Controller - Check if parameter passed to method inside controller is a Model

Basically, all i want to do is check if the object passed to the method is a model. Doesn't matter what the model is, I just want to make sure its a model. So i tried typecasting the $resource variable/parameter with Model $resource however this returned an error.
Argument 1 passed to App\Http\Controllers\Handlers\FileUploadHandler::replaceFile() must be an instance of App\Http\Controllers\Handlers\Model, instance of App\Models\Resource\Ingredient given, called in E:\Sites\kara\app\Http\Controllers\Resources\IngredientsController.php on line 109
Here is my method:
// Handle File Replacement
public static function replaceFile( $resource, Request $request, $storageFolder = 'noPath', $formName = 'fileUpload') {
// Delete the old file
Storage::delete($resource->fullPath);
// Place the new file
return self::uploadFile($request, $storageFolder, $formName);
}
Here is how i'm calling it:
// Create the object
$ingredient = Ingredient::where('id', $id)->first();
$file = FileUploadHandler::replaceFile($ingredient, $request, 'ingredients');
To check if some variable is pointing to a Model you can use instanceof.
Example:
<?php
class A{};
class B extends A{};
$obj = new B();
if ($obj instanceof A) {
echo 'yes';
}
Output: yes
Figured it out:
You have to add the Illuminate\Database\Eloquent\Model class in your use statements.
So when you call Model $resource it will return ok.

Set $pageName globally in pagination Laravel

We can use a custom $customPageName in laravel's paginate() function's 3rd parameter.By that we can use site.com/url?$customPageName=n . Is there any way we can set the custom page name globally ? In AppServiceProvider or somewhere like that?So we don't need to define every time?
There are many possible solution. I give you two that IMO are the best:
1: Create a trait and use it in every component
I love to use traits, they avoid a lot of redundancy and can be easily invoked everywhere:
trait PaginationTrait
{
const PAGE_NAME = 'your_global_value'
public function paginate($query, $perPage, $columns = [''], $page_name = null)
{
return $query->paginate($perPage, $columns, $page_name ?: self::PAGE_NAME);
}
}
This solution requires anyway that you pass as input a Builder instance, and may cause a logic problem. So let's move to the next solution
2: Config files
Simply set a variable in an existing config file or in a new config file:
// Example: app.php
return [
// [...]
'page_name' => 'your_custom_value' // or env('APP_PAGE_NAME', 'your_custom_value'),
// [...]
];
And in your controller you can retrive the value as follows:
public function index() {
// [...]
$result = MyModel::paginate($per_page, $columns, config('app.page_name'));
}
3: App\Http\Controllers\Controller
The third solution is the easiest. Set a constant in your App\Http\Controllers\Controller class (as I wrote for the trait part) and by the OOP rules, it will be inherited to all your controllers:
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
const PAGE_NAME = 'your_global_value';
}
And in your controller:
public function index() {
// [...]
$result = MyModel::paginate($per_page, $columns, self::PAGE_NAME);
}
In my opinion, if you simply have to set this global variable, solution 2 and 3 are the best... If you have to create a custom pagination logic, then I think that creating a specific Trait or Class is a good choice

Laravel error "Declaration of model/model_name should be compatible with Illuminate\Database\Eloquent\Model"

i am facing a strange issue regarding laravel application. after updating the composer on my production server i am getting this error. My login page showing fine and when i am entering the credentials its showing this error either the credentials wrong or right its always showing the same error.
Error is
Declaration of App\Models\User::update($a_data = NULL, $a_conditions = NULL) should be compatible with Illuminate\Database\Eloquent\Model::update(array $attributes = Array, array $options = Array)
i have searched on internet but found nothing. Please do help. will be thankful.
When overriding a method from parent class - the signature of the method must be exactly the same in terms of parameters and their types
In the parent class, both $attributes and $options are set to be of type array, so you must also set set them this way in your class
namespace App\Models;
class User extends \Illuminate\Database\Eloquent\Model {
...
public function update(array $attributes = [], array $options = []) {
// ... your implementation
return parent::update($attributes, $options);
}
...
}

Same model for two tables

I set the name of my table in my model in the constructor:
public function __construct($section, $attributes = array(), $exists = false){
parent::__construct($attributes, $exists);
$this->table = $section;
}
Later on in the class I use this method:
public function getEdit($id){
return $this->find($id);
}
But it fails:
Missing argument 1 for MyModel::__construct()
Any ideas where I'm going wrong?
If you ever override a method that is provided by another class, you should add your own parameters to the end of the parameter list as optional parameters. The reason being that there will likely be code that relies on the old implementation. You can't expect it to know your new implementation, so you must add your own stuff to the end (and optional because the existing implementation won't be supplying it).
As such, change your constructor to:
public function __construct($attributes = array(), $exists = false, $section = null){
parent::__construct($attributes, $exists);
$this->table = $section;
}
And you should find it works. Obviously you'll have to update your code to pass $seciton as the last parameter now, too.

Resources