Creating models with many variables - codeigniter

Can anyone help me interpret this code?
What does $gallery = false mean? Why mention it instead of just erasing it?
models/post_model.php
public function post($post_parent_ID, $gallery = false)
{
}

If you want to pass any default value for any argument, you need to write it like this.
Then why it's false - Because by default, you don't like to use it. But you have kept an option for future use. Now when you pass second argument with any other value, it will work. Otherwise, your function will work by using first argument.

Function parameters can sometimes be optional, which means they don't need to contain any data.
public function post($post_parent_ID, $gallery = false)
{
}
Means that when I'd send something to this function I can do:
$this->post(1);
or
$this->post(1, 2);
Inside the post function you would check wether $gallery is filled or not depending on the use needed.

Related

How to optionally call mutator in lumen

i use mutator in my model to encrypt id:
public function getIdAttribute($value)
{
return encrypt($value);
}
but I want the default value to be the original value of the id and call the mutator when needed. is that possible?
If you want to be able to call the original value, and sometimes the encrypted value why don't you just add an extra function to your model ?
You won't use a mutator since you want to be able to grab the original value, but you can add an extra function like this in your model which you will be able to call when you want to receive encrypted value.
public function encryptedId()
{
return encrypt($this->id);
}
Or am I missing something?
You can using getRawOriginal() to get original value in lumen:
for example:
$model = Model::find('model_id');
return $model->getRawOriginal('column_name'));

Shopware 6: Changing URL parameters returns the same result in prod mode

We extended the product listing to contain the specific paramter "property-groups" which influences the output.
All works fine in dev mode, but when switching to prod mode, changing that parameter does not have any effect any more.
It seems this is cached, but why is that, even the URL parameters change?
i.e.
/widgets/cms/navigation/67e6a05deae747e984a622c7e94e6881?no-aggregations=1&order=name-asc&p=1&property-groups=385b9ebbfc8e450bac9c4d63052ddf7f&slots=7b2547b253a145468fa35eb684b26a62
returns the same like
/widgets/cms/navigation/67e6a05deae747e984a622c7e94e6881?no-aggregations=1&order=name-asc&p=1&property-groups=&slots=7b2547b253a145468fa35eb684b26a62
If we flush the full cache, the second call works and returns the right result.
We of course do not want to fully disable the caching, so we probably have to tell Shopware 6 somehow, to use the new parameter in the cache key.
But we could not find, where the caching happens by debbuging through \Shopware\Storefront\Controller\CmsController::category.
Problem seems to be this:
\Shopware\Core\Content\Product\SalesChannel\Listing\CachedProductListingRoute::generateKey
private function generateKey(string $categoryId, Request $request, SalesChannelContext $context, Criteria $criteria): string
{
$parts = [
self::buildName($categoryId),
$this->generator->getCriteriaHash($criteria),
$this->generator->getSalesChannelContextHash($context),
];
$event = new ProductListingRouteCacheKeyEvent($parts, $categoryId, $request, $context, $criteria);
$this->dispatcher->dispatch($event);
return md5(JsonFieldSerializer::encodeJson($event->getParts()));
}
Here a cache key is generated which takes account the standard parameters, but not the new one added by us.
You have to listen for the ProductListingRouteCacheKeyEvent and add your parameter to the parts.
public static function getSubscribedEvents(): array
{
return [
// ...
ProductListingRouteCacheKeyEvent::class => 'addPropertyGroupsCachePart'
];
}
public function addPropertyGroupsCachePart(ProductListingRouteCacheKeyEvent $event)
{
$event->addPart((string)$event->getRequest()->get('poperty-groups'));
}
This way Shopware generates a unique cache key that is also based on that parameter we introduced and the cache collision disappears.

Handling Failed eloquent methods

I'm calling a product's information field, as you can see below:
$product->attributes->first()->attributeValues->where('locale',$iso);
Basically in the $product variable already have information regarding the product.
I use $product->attributes->first() to get his attributes, and after getting them I go get his values with ->attributeValues->where('locale',$iso) with the specific language.
The data it outputs is good, but only if attributes exist, because in case there isn't any it doesn't and because of the attributeValues method the page fails.
How can I handle in this situation?
You may check it with a simple empty() or even count() if you prefer.
$attributes = $product->attributes->first()->attributeValues->where('locale',$iso);
if (count($attributes) == 0) {
// There is no attribute, do something
}
Split up your line
$attributes = $product->attributes->first(); // placeholder
if(isset($attributes) { // check if we have one
$attributes->attributeValues->where('locale',$iso); // if so.. do the dance
} else {// go home }

Accessing parameters in Request

I have a question about obtaining parameters from Request object.
What is the difference between
$name = $request->name;
OR
$name = $request->input("name");
They show the same behavior. I am asking that from the typing perspective, it is faster to utilize #1 method. But I don't know the difference. Is #1 prone to SQL injections?
Basically, the first case is just a syntactic sugar for the second. In Laravel, Request implements __get magic function to access its internal properties.
public function all()
{
return array_replace_recursive($this->input(), $this->allFiles());
}
public function __get($key)
{
$all = $this->all();
if (array_key_exists($key, $all)) {
return $all[$key];
} else {
return $this->route($key);
}
}
In the first case, if any files were uploaded, Laravel first looks for a property amongst them. And if there is no such param in files or in input, in your first snippet, Laravel also looks for a value amongst route parameters:
To protect your code against SQL injections, you have to use prepared statements/query builder/ORM. You should not escape/change input, so both these functions don't protect you against SQL injections.

How to build an anchor in CodeIgniter where you want to change a variable that is already present in the URI?

Normally I would just use URL GET parameters but CodeIgniter doesn't seem to like them and none of the URL helper functions are designed for them, so I'm trying to do this the 'CodeIgniter way'.
I would like to build a page where the model can accept a number of different URI paramters, none necessarily present, and none having to be in any particular order, much like a regular URL query string with get parameters.
Let's say I have the following url:
http://example.com/site/data/name/joe/
Here not including the controller or the method there would be one parameter:
$params = $this->uri->uri_to_assoc(1);
print_r($params);
// output
array( [name] => [joe] )
If I wanted 'joe' to change to 'ray' I could do this:
echo anchor('name/ray');
Simple enough but what if there are more parameters and the position of the parameters are changing? Like:
http://example.com/site/data/town/losangeles/name/joe/
http://example.com/site/data/age/21/name/joe/town/seattle
Is there a way to just grab the URL and output it with just the 'name' parameter changed?
Edit: As per landons advice I took his script and set it up as a url helper function by creating the file:
application/helpers/MY_url_helper.php
Basically I rewrote the function current_url() to optionally accept an array of parameters that will be substituted into the current URI. If you don't pass the array the function acts as originally designed:
function current_url($vars = NULL)
{
$CI =& get_instance();
if ( ! is_array($vars))
{
return $CI->config->site_url($CI->uri->uri_string());
}
else
{
$start_index = 1;
$params = $CI->uri->uri_to_assoc($start_index);
foreach ($vars as $key => $value)
{
$params[$key] = $value;
}
$new_uri = $CI->uri->assoc_to_uri($params);
return $CI->config->site_url($new_uri);
}
}
It works OK. I think the bottom line is I do not like the 'CodeIgniter Way' and I will be looking at mixing segment based URL's with querystrings or another framework altogether.
You can use the assoc_to_uri() method to get it back to URI format:
<?php
// The segment offset to use for associative data (change me!)
$start_index = 1;
// Parse URI path into associative array
$params = $this->uri->uri_to_assoc($start_index);
// Change the value you want (change me!)
$params['name'] = 'ray';
// Convert back to path format
$new_uri = $this->uri->assoc_to_uri($params);
// Prepend the leading segments back to the URI
for ($i=1; $i<$start_index; $i++)
{
$new_uri = $this->uri->segment($i).'/'.$new_uri;
}
// Output anchor
echo anchor($new_uri);
I'd recommend wrapping this in a helper function of some sort. Happy coding!
Why not use CodeIgniter's built in URI Class? It allows you to select the relevant segments from the URL which you could use to create the anchor. However, unless you created custom routes, it would mean that your methods would need to accept more parameters.
To use the URI Class, you would have the following in your method:
echo anchor($this->uri->segment(3).'/ray');
Assuming /site/data/name are all CodeIgniter specific (/controller/method/parameter)
Now, I think this could be made a lot easier if you were using routes. Your route would look like this:
$route['site/data/name/(:any)'] = 'site/data/$1';
Effictively, your URL can be as detailed and specific as you want it to be, but in your code the function is a lot cleaner and the parameters are quite descriptive. You method would defined like this:
function data($name) { }
To extend your route to accept more parameters, your route for the the example URL "http://example.com/site/data/age/21/name/joe/town/seattle" you supplied would look like this:
$route['site/data/age/(:num)/name/(:any)/town/(:any)'] = 'controller/data/$1/$2/$3';
And your function would look like this:
function data($age, $name, $town) { }

Resources