We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 26709
    • 4 Posts
    Уважаемые соплеменники smiley

    Решил для личных нужд написать сниппет для создания корзины заказов. Обычную корзину, которая собирает данные о выбранных пользователем товарах, подсчете стоимости и отправке заказа на мыло ему и админу (без оплаты).

    Вышла новая версия модуля v4.6.2.1 beta. Обновлено 25.10.12

    Версия в стадии beta, поскольку внесено много новых возможностей и необходимо тестирование и доработки. Но вы можете смело использовать ее в ваших проектах, поскольку она наследовала уже проверенные временем наработки предыдущей версии.

    Полный список изменений читайте в документации. Но вот некоторые:

    1) Добавлена возможность манипулировать ценами товаров. Если вам нужно менять цену товара в зависимости от количества единиц заказанного товара, то у вас есть легкий способ это осуществить.

    Рассмотрим пример. Представьте, что у вас есть товар, у которого цена зависит от количества заказанных единиц. Например, если заказать от 1 до 5 штук, то цена товара 100 руб, если от 6 до 10 - то цена 90, а в остальных случаях 80 руб. Чтобы это реализовать, в поле ЦЕНА, в ТВ price вместо обычной цены достаточно указать простую формулу:

    [tt]1-5==100||6-10==90||80[/tt]

    И цена товара динамически изменится.

    2) Добавлена возможность задавать дополнительные параметры товара: цвет, размер и т.д. При этом каждый параметр может определенным образом влиять на общую стоимость товара. Причем не только приплюсовываться к стоимости, а и отниматься и даже умножаться. Т.е. наподобие такого: Сумма = стоимость + param1 + param2 - param3.

    3) Сделана шаблонизация корзины и инфоблока.

    Более полный список изменений читайте в документации.

    Обновление 14.01.2016. Проект TSVshop развивается, теперь он переехал на новый сайт http://tsvshop.xyz
    Последняя актуальная версия на 14.01.2016 - TSVshop v5.3. Скачать можно либо на сайте, либо на https://github.com/Serg28/tsvshop/releases

    [ed. note: Serg24 last edited this post 8 years, 2 months ago.]
      • 785
      • 2,113 Posts
      Мне кажется, лучше сначала выбрать какой-то имеющийся вариант за основу, а потом обсудить, что в нем надо исправить. Разрабатывать с нуля, я думаю, вряд ли нужно.
        Создание сайтов на MODx, поддержка сайтов, поисковая оптимизация, программирование, копирайтинг
        Статьи о MODx, регулярно новые публикации
        • 26709
        • 4 Posts
        В принципе, да. С нуля разрабатывать может и не нужно, хотя ковырять чужой код особо нету удовольствия. Хотя у меня есть 2 варианта неплохой корзины. Можно попробоватьее переделать под МОДх. Кому интересно, вылаживаю их здесь.

        Первый вариант, взять за основу сниппет из Этомите.

        ###########################################################################################################
        ##	SNIPPET: etoBasketV1.2											
        ##	DATE: 16/9/07												
        ## 	BY:  Cris D for Etomite CMS									
        ##	USE: Creates multiple item shopping page that allows users to purchase 				
        ##	items through paypal											
        ##														
        ##	LIMITATIONS: Due to the complex and changing field of on-line shopping, this snippet			
        ##	is designed as a base to start from and must be cusomised for individual use.	
        ##	Individual circumstances change dramatically, therefore only assistance with the snippet code logic	
        ##	will be offered in the etomite forums. For paypal assistance, please see paypal.com.			
        ##											
        ##	INSTALLATION INSTRUCTIONS: Copy and paste this code into your snippet library.				
        ##	Change the items requiring configuration.  Save it as etoBasket.	
        ##	Call the snippet in a page [!etoBasket!] and start entering your items for sale.			
        ##													
        ##	SECURITY and LOGGING IN: If you will need to have authenticate_visitor on your site to log in and
        ##	enter data or place a snippet call ?permission=1 to temporarily override the authentication.		
        ##														
        ##	MORE: More documentation can be found in the etomite forum, snippet library / etoBasket.		
        ##	CREDITS: robsta for the initial paypal snippet, Ralph and Dean for Etomite!	
        ##      UPDATES: 2007/11/17 Fixed some minor validation issues
        #############################################################################################################
        
        ########## CONFIGURE THIS SNIPPET ##################
        //Set the default folder for pictures (this can be overwritten on individual items if required)
        $default_pic_folder=isset($default_pic_folder) ? $default_pic_folder:"assets/images/";//set the the default image folder
        //set the table name (allows mutliple installations).
        $tableName="etobasket";
        //$paypalChunk=""; Optional, set the name of the chunk you would like to use to display the items.
        //Why not copy and paste the InternalTemplate as a new chunk and play with it.  
        //If it doesn't work, simply clear this field  to revert to the original one.
        $paypalChunk="";
        
        ######## PAYPAL VARIABLES #############
        //An explaination of these variables can be seen at
        //https://www.paypal.com/IntegrationCenter/ic_std-variable-reference.html#HTMLVariablesforShoppingCarts
        
        // Email account to pay the money to.
        $PAYPAL_BUSINESS= "[email protected]";
        $PAYPAL_IMAGE = "https://www.paypal.com/en_GB/i/btn/x-click-but22.gif";           //Default payment button image
        $PAYPAL_IMAGE_ALT = "Make payments with PayPal - its fast, free and secure!";     //Default payment button mouseover text
        $PAYPAL_ADD = "1";                      //default number of items
        $PAYPAL_CMD = "_cart";			//paypal requirement
        $PAYPAL_PAGE_STYLE = "Primary";		//set to the cart style in your account
        $PAYPAL_RETURN_PAGE_ID = "0";		//id of page returned to on completion of transaction                                 
        $ref="ID";				//this separates the item name and the id reference number.  Use...Ref, ID, RE, Code etc.
        $PAYPAL_NO_NOTE = "1";			//1=Request customers to leave a note on purchase 0= no notes
        $PAYPAL_CURRENCY_CODE = "AUD";       	// currency setting
        $PAYPAL_LC = "AUS";                  	// currency setting
        $currencyIcon="$";			// currency setting (optional- can confuse international customers and paypal)
        $ViewCart="View Cart";                  // Set for the text (or img src to the button to use)to show as the link
        
        //some inline styling for an item wrapping div to get immediate results.  
        //This is not used if an external chunk ($payPalChunk) is being used (external chunk and CSS preferred).
        $inlineStyling='float:left; 
        		display:block; 
        		padding:20px; 
        		margin:10px; 
        		width:100%; 
        		background:#ccffff url(templates/AlexisProRedux/images/section.jpg); 
        		margin:2px; 
        		padding:2px;';
        
        
        ########### END SNIPPET CONFIGURATION  ###################
        ##     The rest should take care of itself...		##
        ######### Automatic Snippet variables ####################
        $host = 	$GLOBALS['database_server']; 
        $user = 	$GLOBALS['database_user']; 
        $pass = 	$GLOBALS['database_password']; 
        $dbase=    trim($GLOBALS['dbase'],'`');//database
        $baseURL=	$GLOBALS['www_base_path'];
        $etoPrefix=$GLOBALS['table_prefix'];//automatically set to the prefix of the etomite installation.
        $userlog=$etomite->userLoggedIn();
        $page=$etomite->documentIdentifier;
        $permission=0;
        $permission=$etomite->checkPermissions();
        $tableCheck=$etomite->extTableExists($host, $user, $pass, $dbase, $table=$etoPrefix.$tableName);
        
        $extractedId=explode(':',$_GET['record']);
        
        ####### SNIPPET TEMPLATES #############
        //Copy and paste Internaltemplate to use as a start for an external chunk.
        //This is the main formatting of the items that the public see/
        
        //Create a "Proceed to checkout" button.
        $ViewCart=
        <<<END
        <a href="https://www.paypal.com/cart/display=1&business=$PAYPAL_BUSINESS&" target="paypal">$ViewCart</a>
        END;
        
        
        $InternalTemplate=
        <<<END
        <div class='ppal_item' style='$inlineStyling'>
        <img src='{baseURL}{pic_folder}{filename}' alt='{filename}'/><br />
        <div class='ppal_text' style='float:left;'>Item: {item} <br /> Description: {text}<br />Price:{currency_icon}{pp_currency_code}{price}</div>
        <div style='float:right;'><form action='https://www.paypal.com/cgi-bin/webscr' target="paypal" method='post'>
        <input type='image' src='{pp_image}' name='submit' alt='{pp_image_alt}' />
        <input type='hidden' name='add' value='{pp_add}' />
        <input type='hidden' name='cmd' value='{pp_cmd}' />
        <input type='hidden' name='business' value='{pp_business}' />
        <input type='hidden' name='item_name' value='{item}{ref}: {id}' />
        <input type='hidden' name='amount' value='{price}' />
        <input type='hidden' name='page_style' value='{pp_page_style}' />
        <input type='hidden' name='return' value='{baseURL}index.php?id={returnPage}' />
        <input type='hidden' name='no_note' value='{pp_no_note}' />
        <input type='hidden' name='currency_code' value='{pp_currency_code}' />
        <input type='hidden' name='lc' value='{pp_lc}' />
        </form></div>
        </div>
        END;
        
        //formNew creates a blank form for new records with some default values already added.
        $formNew.="<p> </p><h1>Add New Item</h1>";
        $formNew.=
        <<<END
        <form action="" name="etoBasket" method="POST" />
        <input type="hidden" name="prefix" value="bskt_" />
        <input type="hidden" name="into" value="$tableName" />
        <input type="hidden" name="bskt_id" value="" />
        <label for="item">Item: </label>
        	<input type="text" name="bskt_item" id="item" value="" /><br />
        <label for="description">Description:</label>
        	<textarea name="bskt_description" id="description" rows="3" cols="40"></textarea><br />
        <label for="price">Price:$PAYPAL_CURRENCY_CODE $currencyIcon</label>
        	<input type="text" name="bskt_price" id="price" value="" /><br />
        <label for="pic_folder">Pic URL:</label>
        	<input type="text" name="bskt_pic_folder" id="pic_folder" value="$default_pic_folder" />
        <label for="filename">Pic Filename:</label>
        	<input type="text" name="bskt_filename" id="filename" value="defaultimage.jpg"/><br />
        <label for="onPage">Show on page:</label>
        	<input type="text" name="bskt_onPage" id="onPage" value="$page"/>This page id is: $page<br />
        <label for="active">Active?</label>
        	<input type="text" name="bskt_active" id="active" value="$active"/>Set to "1" to show on page<br />
        <input type="submit" name="sub" value="Send it off" />
        </form><p> </p>
        END;
        
        ######## END SNIPPET TEMPLATES ########
        
        
        ########### Define Snippet Function #####################
        if (!function_exists('stripslashes_deep')){
        
        function stripslashes_deep($value){
            $value = is_array($value) ?
                        array_map('stripslashes_deep', $value) :
                        stripslashes($value);
        
            return $value;
        		}
        
        	}
        #########################################################
        //Try to get external chunk 
        $chunkName=$etomite->getChunk($paypalChunk);
        //or use internal chunk if none provided.
        if(empty($chunkName))$chunkName=$InternalTemplate;
        
        //If logged in, show managers forms...
        if($permission==1){
        		//check if table exists, if not make it
        		if($tableCheck!=1){
        			$sql = 'CREATE TABLE `'.$etoPrefix.$tableName.'` ('
                		. ' `id` INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY, '
                		. ' `item` VARCHAR(100) NULL, '
                		. ' `description` VARCHAR(500) NULL, '
                		. ' `price` VARCHAR(10) NULL, '
                		. ' `pic_folder` VARCHAR(50) NULL, '
                		. ' `filename` VARCHAR(20) NULL, '
                		. ' `onPage` INT( 10 ) NULL, '
                		. ' `active` ENUM(\'1\',\'0\') NOT NULL DEFAULT \'1\''
                		. ' )'
                		. ' ENGINE = myisam;';
        			$etomite->dbQuery($sql);
        			}
        	//delete records if requested to
        	if(isset($_POST['delete']) ){
        	//unless you change your mind!
        	if(!isset($_POST['keep'])){
        		$id=isset($id)? $id:$_POST['bskt_id'];
        	$confirmDelete="<form action='' method='post'>\n
        			<input type='hidden' name='delete'>\n
        			<input type='hidden' name='bskt_id' value='$id'>\n
        			<input type='submit' name='confirm' value='DELETE'>\n
        			<input type='submit' name='keep' value='NO'>\n";
        	if(!$_POST['confirm']){return "Delete record...".$id.": ".$_POST['bskt_item']."?<br />".$confirmDelete;}
        		if(isset($_POST['confirm'])){
        			$sql.="DELETE FROM `".$etoPrefix."".$tableName."` WHERE `".$etoPrefix."".$tableName."`.`id` =".$id." LIMIT 1";
        			$con=$etomite->dbQuery($sql);
        			unset($id);
        			}
        		}
        	}
        	//has new or changed form data been sent off? If so save it.
        	if(isset($_POST['sub'])){
        
        		$table=$_POST['into'];
        
        		$fields=array();
        
        		$fields = $etomite->getFormVars($method="POST", $prefix="bskt_", $trim=1, $REQUEST_METHOD);
        
        		foreach($fields as $key=>$value) {
        			$fields[$key] = addslashes($value);
        			}
        
        		if($fields['id']=="" OR $fields['id']=="{id}") {
        
        		$rs = $etomite->putIntTableRow($fields, $table, $addPrefix=true);
        		} else {
        		$rs = $etomite->updIntTableRows($fields, $table, $where="id=".$fields['id'], $sort="", $dir="ASC",$limit="",
        		$addPrefix=true);
        		}
        	}//closing bracket for if save details have been sent
        
        //get all records to populate the select drop down box.
        	$rsARaw=$etomite->getIntTableRows($fields="*",$from=$tableName,$where='',$sort='',$dir='',$limit="9999",
        	$push=true,$addPrefix=true);
        	
        	$rsA=stripslashes_deep($rsARaw);
        	$counta=count($rsARaw);
        //Create drop down select box to get existing records to edit.
        	$select.="<br /><form action=\"".$etomite->makeURL($page,'','')."\" method=\"get\">\n";
        	$select.="<input type=\"hidden\" name=\"id\" value=\"$page\">\n";
        	$select.="<label for=\"select\">Choose record:</label><select name=\"record\" id=\"select\">\n";
        	if($counta>1){
        		foreach ($rsA as $i){
        			$select.="<option label='".$i['id']."'";
        			if($extractedId[0]==$i['id']){$select.=" selected";}
        				$select.=">".$i['id'].": ".$i['item']."</option>\n";
        			}
        	}else{
        	$select.="<option label='".$rsA[0]['id']."' selected>".$rsA[0]['id'].": ".$rsA['item']."</option>\n";
        	}
        	$select.="</select><input type=\"submit\" name=\"recsub\" value=\"Get record\" /></form>";
        
        //If select form is sent to collect a record get the record to show
        	if(!empty($extractedId[0])){$where="id=".$extractedId[0];}else{$where='';}
        
        	$rsBRaw=$etomite->getIntTableRows($fields="*",$from=$tableName,$where,$sort,$dir,$limit="9999",
        	$push=true,$addPrefix=true);
        	$rsB=stripslashes_deep($rsBRaw);
        //Pre-fill in the forms with existing item data...
        	$countb=count($rsBRaw);
        	for($i=0;$i<$countb;$i++){
        		$id		=$rsB[$i]['id'];
        		$item		=$rsB[$i]['item'];
        		$description	=$rsB[$i]['description'];
        		$price		=$rsB[$i]['price'];
        		$pic_folder	=$rsB[$i]['pic_folder'];
        		$filename	=$rsB[$i]['filename'];
        		$onPage		=$rsB[$i]['onPage'];
        		$active		=$rsB[$i]['active'];
        
        //this form is the one that contains the existing records and is repeated for each item
        
        $form.="<img src='$baseURL".$pic_folder.$filename."' />";
        $form.=
        <<<END
        <form action="" name="etoBasket" method="POST" />
        <input type="hidden" name="prefix" value="bskt_" />
        <input type="hidden" name="into" value="$tableName" />
        <input type="hidden" name="bskt_id" value="$id" />
        <label for="item">Item: </label>
        	<input type="text" name="bskt_item" id="item" value="$item"/><br />
        <label for="description">Description:</label>
        	<textarea name="bskt_description" id="description" rows="3" cols="40">$description</textarea><br />
        <label for="price">Price:$PAYPAL_CURRENCY_CODE $currencyIcon</label>
        	<input type="text" name="bskt_price" id="price" value="$price" /><br />
        <label for="pic_folder">Pic URL:</label>
        	<input type="text" name="bskt_pic_folder" id="pic_folder" value="$pic_folder" />
        <label for="filename">Pic Filename:</label>
        	<input type="text" name="bskt_filename" id="filename" value="$filename"/><br />
        <label for="onPage">Show on page:</label>
        	<input type="text" name="bskt_onPage" id="onPage" value="$onPage" />This page id is: $page<br />
        <label for="active">Active?</label>
        	<input type="text" name="bskt_active" id="active" value="$active" />Set to "1" to show on page <br />
        	<input type="submit" name="delete" value="Delete">
        	<input type="submit" name="sub" value="Save">
        </form>
        END;
        
        }//closing bracket for generating pre-filled forms
        	//if a record has not been requested, put a blank form at the top of the page.
        	if(!$_GET['recsub']){
        		return $select.$formNew.$form;
        	}else{
        	//else put the requested record at the top and a blank one at the bottom.
        		return $select.$form.$formNew;
        	}
        }//closing bracket for showing managers forms.
        
        ##########################################################################
        ##	      If not logged in, then show the public stuff...		##
        ##########################################################################
        //Display item selection based on page id  set or default: show all
        $showSelection="onPage=".$page." AND active=1";
        $where=$showSelection;
        
        $rsCRaw=$etomite->getIntTableRows(
        $fields="*",$from=$tableName,$where,$sort,$dir,$limit="9999",$push=true,$addPrefix=true);
        
        $rsC=stripslashes_deep($rsCRaw);
        
        $countC=count($rsCRaw);
        for($i=0; $i<$countC; $i++){
        	$PAYPAL_INFO[]=array(
        	'item'		=>	$rsC[$i]['item'],
        	'price'		=>	$rsC[$i]['price'],
        	'text'		=>	$rsC[$i]['description'],
        	'id'		=>	$rsC[$i]['id'],
        	'pic_folder'	=>	$rsC[$i]['pic_folder'],
        	'filename'	=>	$rsC[$i]['filename'],
        	'active'	=>	$rsC[$i]['active'],
        	'pp_business'	=>	$PAYPAL_BUSINESS,
        	'pp_image'	=>	$PAYPAL_IMAGE,
        	'pp_image_alt'	=>	$PAYPAL_IMAGE_ALT,
        	'pp_add'	=>	$PAYPAL_ADD,
        	'pp_cmd'	=>	$PAYPAL_CMD,
        	'pp_page_style'	=>	$PAYPAL_PAGE_STYLE,
        	'currency_icon'	=>	$currencyIcon,
        	'pp_currency_code'=>	$PAYPAL_CURRENCY_CODE,
        	'pp_no_note'	=>	$PAYPAL_NO_NOTE,
        	'pp_lc'		=>	$PAYPAL_LC,
        	'baseURL'	=>	$baseURL,
        	'ref'		=>	$ref,
        	'returnPage'	=>	$PAYPAL_RETURN_PAGE_ID,
        	);
        }
        //output the data with the template...
        
        $output.=$etomite->mergeCodeVariables(
        $content=$chunkName,
        $rs=$PAYPAL_INFO,
        $prefix="{",$suffix="}",
        $oddStyle="class=\"pp_odd\"",$evenStyle="class=\"pp_even\"",//set these in your css to control how it looks
        $tag="div"
        );
        
        return $ViewCart.$output.$ViewCart;


        пробовал его в работе, выдает белую страницу. Видимо, где-то ошибка или несовместимость с МОДх. Просто небыло возможности разбираться.

        Второй вариант в приложенном архиве. Там считываются поля методом ПОСТ, потом эти данные записываются в текстовый файл. после чего идет дальнейшая обработка. В принципе, скриптик неплохой, но надо бы перевести на БД и доработать.

        Третий вариант - просто сделать все с нуля. о чем предлагал выше.

        Теперь кому интересно, можете поковырять приложенные мной варианты и сказать ваши идеи. Есть ли смысл делать на их основе или же сделать все свое - не сильно навороченно но тем не менее вложить нужный функционал уже с самого начала.

        Жду идей smiley
          • 26709
          • 4 Posts
          Уважаемые господа!
          Спешу обрадовать вас. Я сделал на основе найденного мной скрипта прекрасную корзину с возможностью добавления товаров, подсчетом и выводом результатов. Прерасная интеграция в шаблоны с ДИТТО.

          На днях выложу готовые сниппеты + документацию. которые начну писать завтра.
            • 32085
            • 17 Posts
            Неплохая идея заложена в ShopX, к нему бы еще добавить возможности из gCart,
            переработав их, можно сделать мне кажется достаточно гибкую и функциональную корзину.

              • 26770
              • 74 Posts
              Quote from: Serg24 at Mar 26, 2008, 09:42 PM

              На днях выложу готовые сниппеты + документацию. которые начну писать завтра.
              Это ооочень хорошо! Заранее огромное спасибо!
              Если, что, могу помочь с документацией. Так как в ПХП особо не силен, а с модиксом пару месяцев. Но есть огромное желани работать в этом направлении.
                • 26709
                • 4 Posts
                Первые испытания прошли успешно smiley установка на МОДх прошла буквально за 5 мин., работает как часы. Внешний вид корзины и всего остльного элементарно, настройка самой корзины - всего в 1 файле, больше 20 языковых локализаций, в т.ч. и русский. Только немного подождите, все выложу, т.к. у меня много работы и нужно сниппеты привести в порядок. Как только все сделаю, сразу выложу
                  • 4735
                  • 51 Posts
                  Ну наконец-то дождались, поскорей бы уже произошло "явление корзины народу" smiley
                    Интернет-магазин стильной мужской одежды - http://www.dotmind.ru
                    • 593
                    • 56 Posts
                    В предвкушении smiley
                      • 26709
                      • 4 Posts
                      сообщаю о стадии работы. smiley Доделываю документацию. Сегодня-завтра выложу.